GHC 7.0.x―7.2.1 現在のスレッド実装について

GHC (Haskell) のスレッド実装について議論する時の参考になるよう、GHC 7.2.1 までのスレッド実装についてのやり取りやメモ的なつぶやきをまとめておきます。
10
shelarcy(しぇらーしぃ) @shelarcy

@kazu_yamamoto non-threaded STM では TVar が一つのネイティブスレッド上でしか実行されないことが保障されているので実装上ではロックをかけなくても良い。この実装の違いが1 コアでの性能差になっているみたいです http://j.mp/hGaHme

2011-03-28 18:01:01
shelarcy(しぇらーしぃ) @shelarcy

@kazu_yamamoto このように threaded な RTS と non-threaded な RTS に求められるスペックの違いから、1コア同士の比較なら threaded な実装は non-threaded な実装に比べて遅くなるということです。

2011-03-28 18:06:23
shelarcy(しぇらーしぃ) @shelarcy

@kazu_yamamoto で、この1jコア同士の性能低下が複数コアの場合にも見られるかもしれないから、複数コアで性能をあげたい場合にはちゃんとそれに適した(スケールする)プログラムを書いてね(また性能比較も重要)、と釘を刺しているのが RWH の p.556 の話のはずです。

2011-03-28 18:16:10
shelarcy(しぇらーしぃ) @shelarcy

@kazu_yamamoto MVar でもやはり threaded な RTS ではロックをかけている(厳密にはロックに相当する処理を行っている)のに対し、non-threaded な RTS ではロックをかけないという違いがありました。 http://j.mp/i6PEGr

2011-03-28 19:26:08
shelarcy(しぇらーしぃ) @shelarcy

@kazu_yamamoto はい。atomicModifyIORef では(ソフトウェア的な)ロックではなく、アトミック命令を使って処理の競合を解決しています。 http://j.mp/mPHQOg http://j.mp/nrS6kv http://j.mp/r8C8FF

2011-07-06 21:44:46
shelarcy(しぇらーしぃ) @shelarcy

@kazu_yamamoto .。oO(本当に全くロックをかけていないかどうかは、もうちょっとちゃんと実装を確かめてみる必要がありますが。)

2011-07-06 21:45:44

注意: IORef に格納されるのはサンクで、atomicModifyIORef では単純に(格納された値を表現する)サンクを atomic に更新するだけです。サンクによって評価されるべき値がまるごと更新されるわけではありません。

"A monad for deterministic parallelism" [http://research.microsoft.com/en-us/um/people/simonpj/papers/parallel/ ] より "the difference is that the update is performed atomically; the contents of the IORef are replaced by a lazy thunk representing the result."

上で紹介した "Scalable I/O Event Handling for GHC" や "Generational garbage collection and floating garbage" [http://blog.johantibell.com/2010/04/generational-garbage-collection-and.html] なども参照のこと。

MVar のロック

shelarcy(しぇらーしぃ) @shelarcy

@kazu_yamamoto ここで言うロックは、Spinlock + yieldThread(unix では sched_yield)で自作したものですね。 http://j.mp/oc5K5G http://j.mp/pIxSu4 http://j.mp/nfynVm

2011-07-06 21:46:27
shelarcy(しぇらーしぃ) @shelarcy

@kazu_yamamoto futex は思ったほど性能がでないという理由で。現在は直接呼び出してはいません。 http://hackage.haskell.org/trac/ghc/ticket/3553#comment:5

2011-07-06 21:52:45
shelarcy(しぇらーしぃ) @shelarcy

@kazu_yamamoto 1年半前の Linux 事情を反映したものなので、現在はちゃんと性能が出る状況になっているかもしれませんが。c.f. http://www.atmarkit.co.jp/flinux/rensai/watch2009/watch11a.html

2011-07-06 21:53:49
shelarcy(しぇらーしぃ) @shelarcy

@kazu_yamamoto 見た感じ MVar と IORef の実装には mutex (や futex)は使われていないので、RTS で GC やスレッドのスケジューリングなどの処理を行う際に利用される mutex が結果として現れている感じではないでしょうか?

2011-07-06 21:59:26
shelarcy(しぇらーしぃ) @shelarcy

@kazu_yamamoto あるいは、RTS やライブラリで利用するシステムコールの内部で呼ばれる futex が結果として現れている感じかしら。実際に Linux のシステムコールの実装を見てみないことには、確かなことは言えませんが。

2011-07-06 22:02:45
shelarcy(しぇらーしぃ) @shelarcy

@kazu_yamamoto あっ、「直接呼び出していない」と書くよりも「GHCの実装には使ってません」とストレートに書いた方が良かったかもしれませんね。 > futex

2011-07-06 22:17:19
shelarcy(しぇらーしぃ) @shelarcy

@kazu_yamamoto というわけで、前に書いていた 「-threaded RTS の MVar では、コンテキストスイッチが起こる」という直感は正しいですね。yieldThread(sche_yield)を使ってわざとコンテキストスイッチを起こしていると言う形ですが。

2011-07-06 22:09:28

STM や TVar のロック

shelarcy(しぇらーしぃ) @shelarcy

前に話題になっていた GHC の STM の実装を見てました。threaded RTS だと、cas を使って lock を実装 → それを使って STM を実装という感じですね。 http://t.co/2u4V1mwU http://t.co/KEFYBcXe

2011-10-09 19:02:04
shelarcy(しぇらーしぃ) @shelarcy

STM_CG_LOCK はコメントアウトされているため、threaded RTS では STM_FG_LOCKS、threaded でない RTS では STM_UNIPROC の定義が使われるはずです。 http://t.co/nP2YdUCf

2011-10-09 19:02:36
shelarcy(しぇらーしぃ) @shelarcy

どうやら、MVar にしろ [http://t.co/RbydmhOz http://t.co/kTf2Y32C ] 、STM にしろ、GHC の RTS では lock と言っても OS の提供する既成の lock ではなく RTS で自作したものを使っているようです。

2011-10-09 19:04:29
shelarcy(しぇらーしぃ) @shelarcy

GHC 7.2.1現在、OS の提供する lock の使用はScheduler、Taskの生成、削除、GCなどのネイティブスレッドの処理を制御する必要のある部分に限定されている感じですね。 http://t.co/N33SjLDD http://t.co/oPt00WnO

2011-10-09 19:24:21

なお、Scheduler、Task の生成、削除、GC などのネイティブスレッドの処理を制御する必要のある部分での、OS の提供する機能を使ったロック(mutex) の実装は以下のような形になっています。 https://github.com/ghc/ghc/blob/ghc-7.2/includes/rts/OSThreads.h https://github.com/ghc/ghc/blob/ghc-7.2/rts/posix/OSThreads.c#L139 https://github.com/ghc/ghc/blob/ghc-7.2/rts/win32/OSThreads.c#L134

スレッド処理とFFI