17

Haskell のスレッド ( forkIOによって生成されたスレッド) が OS スレッドにどのようにマッピングされているかを正確に調べようとしました。

最初に見つけた情報源は、

http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurrent.html#g:11

すべての軽量スレッドが実際には 1 つの OS スレッドで実行され、Haskell スレッドが安全な IO 操作でブロックする場合にのみ、GHC ランタイムが新しい OS スレッドを生成して他の Haskell スレッドを実行し、IO 呼び出しがブロックしないように指定します。プログラム全体。

2番目の情報源はここから来ています。

http://www.haskell.org/ghc/docs/7.0.1/html/users_guide/using-smp.html

これは、Haskell スレッドが事前に定義された数の事前に作成された OS スレッドにバランスよくマップされていることを明確に示しています。つまり、80 個の軽量スレッドがあり、プログラムを実行するときにオプション +RTS -N 8 を渡した場合、少なくとも 8 つの OS スレッドが作成され、そのような各スレッドが 10 個の軽量スレッドを実行することになります。8 つの CPU コアを搭載したマシンでは、1 コアあたり約 10 の Haskell スレッドを意味します。

2番目の情報源はより正確なもののようであり、-threadedフラグを付けてコンパイルされたプログラムを実行するときにGHCランタイムが明らかになることを望むのは、まさにこの動作です。

誰でもこれを確認できますか? また、2 番目のバージョンが正しい場合、バインドされたスレッド ( forkOSを使用して生成されたもの) の目的は何ですか?それは、スレッド ローカル データを使用するネイティブ コードを処理するためだけですか?

4

1 に答える 1

24

単一の OS スレッドを使用せずにコンパイルされたプログラムは-threaded、すべての Haskell スレッドを実行します。外部呼び出しは、実行中のすべての Haskell スレッドをブロックします。

でコンパイルされたプログラムは、-threaded複数の OS スレッドを使用して複数の Haskell スレッドを並行して実行できます (OS スレッドの数は+RTS -Nオプションで制御できます)。マークされた外部呼び出しは、safe他の実行中の Haskell スレッドをブロックしません (そのため、複数の Haskell スレッドがあり、時間がかかる可能性のある外部呼び出しを発行する場合-threadedでも、使用すると有益な場合があります)。+RTS -N1マークされた外部呼び出しunsafeは、GHC で単純なインライン関数呼び出しとして実装され、呼び出し元の OS スレッドをブロックします。

最初の情報源に関しては、単一の機能の観点から外部呼び出しが発行されたときに何が起こるかを説明しています。機能は、Haskell コードを実行するための仮想 CPU として定義されます。スレッド化された RTS では、OS スレッドのコレクションに対応し、常にそのうちの 1 つだけが Haskell コードを実行します (他の OS スレッドは、Haskell をブロックすることなく外部呼び出しを行うために使用されます)。スレッド)。Haskell スレッドがsafe外部呼び出しを行うと、中断されたスレッドのリストに追加され、その機能が別の Haskell スレッドに与えられます

バインドされたHaskell スレッドには、外部呼び出しを行うための固定の関連付けられた OS スレッドがあります。非バインドスレッドには関連付けられた OS スレッドがありません。このスレッドからの外部呼び出しは、任意の OS スレッドで行うことができます。バインドされたスレッドは、レンダリング コンテキストを OS-thread-local-state に格納する OpenGL など、ライブラリへのどの呼び出しがどの OS スレッドから行われるかが重要なライブラリと対話するために使用されます。

詳細については、GHC マニュアルと次の論文を参照してください。

同時実行による Haskell 外部関数インターフェイスの拡張

サイモン・マーロウ、サイモン・ペイトン・ジョーンズ、ウルフガング・タラー、Haskell'04

于 2012-10-17T22:20:34.843 に答える