ghc 6.12.1 マルチコア対応ランタイムシステムについて
DESCRIPTION
2009年Haskell忘年会前哨戦TRANSCRIPT
![Page 1: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/1.jpg)
GHC 6.12.1GHC 6.12.1マルチコア対応ランタイムシステムマルチコア対応ランタイムシステム
についてについて
id:maoe
![Page 2: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/2.jpg)
id:maoeid:maoe
青江光敏http://d.hatena.ne.jp/maoe/
http://github.com/maoe
Keepalived.confの文法チェッカ
Haskell歴は4年
![Page 3: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/3.jpg)
id:maoeid:maoe
青江光敏http://d.hatena.ne.jp/maoe/
http://github.com/maoe
Keepalived.confの文法チェッカ
Haskell歴は4年
興味を持ったきっかけは、2005年のLLDNでsakai
さんの発表が全く意味不明だったこと
![Page 4: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/4.jpg)
内容は内容は
プログラミングモデルの話はすっ飛ばして
GHC 6.12.1の並列ランタイム性能改善の元となったと思われる論文”Runtime Support for Multicore Haskell”から
5分では時間がない(つっこまれると答えられない)ので要点を絞って
GHCのスレッドモデル
並列ランタイムの仕組み
最適化の試みを少しだけ
![Page 5: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/5.jpg)
GHCGHCのスレッドモデルのスレッドモデル
CPU #3CPU #2CPU #1CPU #0
CPU数と同数程度の
重いOSスレッド(worker threads)
軽いHaskellスレッド(OSスレッドの100x以上軽い)
とても軽いスパーク(sparks)
a `par` b
forkIO a
./a.out +RTS -N
![Page 6: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/6.jpg)
並列ランタイムの仕組み並列ランタイムの仕組み
CPU #3CPU #2CPU #1CPU #0
HaskellExecution Context #1
(HEC)
HEC #2 HEC #3 HEC #4
● An ownership field
● An message queue
● A run queue
● An allocation area
● GC remembered set
● A spark pool
● A worker pool
● An ownership field
● An message queue
...
... ...
![Page 7: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/7.jpg)
並列ランタイムの仕組み並列ランタイムの仕組み
CPU #0
HaskellExecution Context #1
(HEC)
● An ownership field
● An message queue
● A run queue
● An allocation area
● GC remembered set
● A spark pool
● A worker pool
Haskell Execution Context (HEC)
CPUごとに一つ作られる
+RTS -Nで指定する数だけ作られる
worker threadがHaskell threadを実行するのに必要なデータを持っている
“Capability”とか”virtual
processor”とも呼ばれる
![Page 8: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/8.jpg)
並列ランタイムの仕組み並列ランタイムの仕組み
CPU #0
HaskellExecution Context #1
(HEC)
● An ownership field
● An message queue
● A run queue
● An allocation area
● GC remembered set
● A spark pool
● A worker pool
Haskellスレッドの実体はThread State Object
(TSO)というヒープに割り当てられたデータ構造
15 words + sizeof stack + αで小さい
run queueに入っているのをHECが順次round-
robinで実行していく
parで作られるsparkはspark poolに入る
システムの負荷が高くないときに、GCを生き延びた一部のsparkのみspark threadが作られ並列評価される
つまり必ず並列評価されるわけではない
![Page 9: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/9.jpg)
並列ランタイムの仕組み並列ランタイムの仕組み
CPU #0
HaskellExecution Context #1
(HEC)
● An ownership field
● An message queue
● A run queue
● An allocation area
● GC remembered set
● A spark pool
● A worker pool
HECのライフサイクル
message queueのメッセージを処理
run queueのスレッドを走らせる
spark poolにsparkが入っていればspark threadを起動し実行
HEC内でなくglobalな、black hole
poolをpollingして、いずれかのスレッドが実行できるようになったら実行
![Page 10: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/10.jpg)
最適化の例最適化の例
HEC間のspark poolの共有をpushモデルから、work stealing
queueというロックフリーなデータ構造を使うようにした
並列GCの改善
並列コピー式GCでimmutableなオブジェクトを扱うときは同期処理をしないように変更した
remembered setをHECごとに用意して局所性を高めた
ここでもwork stealing queueを使うことでGCのロードバランスをやめ、局所性を高めた
Control.Parallel.Strategiesを使うときに起こるメモリリーク問題を解消した
ThreadScopeが活躍したみたい
どのタイミングでどのHECが頑張っていたのか一目瞭然
![Page 11: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/11.jpg)
まとめというより所感まとめというより所感
純粋関数型は簡単に並列化できるとは言うものの実際に効率的なプログラムにするのは大変
ラインタイムをこつこつと計測して、こつこつとチューニング
GCなどに他の言語でも利用されている技術を適用
Strategy周りはもう少し勉強が必要
速度向上と環境整備でHaskellの並列プログラミングが一般的になっていくといいな
![Page 12: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/12.jpg)
参考文献参考文献
Runtime Support for Multicore Haskell
(たぶん)GHC 6.12.1に取り込まれた改良に関する論文
Multicore Haskell Now! ACM Reflections
par/pseqを使った並列プログラミングに始まり、並行プログラミング、STM、データ並列までマルチコアを活用するための仕組みを一通り解説
サンプルコードが豊富
GHC Commentary
ちょっと情報が古いかもしれないけど参考になる
![Page 13: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/13.jpg)
1
GHC 6.12.1GHC 6.12.1マルチコア対応ランタイムシステムマルチコア対応ランタイムシステム
についてについて
id:maoe
![Page 14: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/14.jpg)
2
id:maoeid:maoe
青江光敏http://d.hatena.ne.jp/maoe/
http://github.com/maoe
Keepalived.confの文法チェッカ
Haskell歴は4年
![Page 15: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/15.jpg)
3
id:maoeid:maoe
青江光敏http://d.hatena.ne.jp/maoe/
http://github.com/maoe
Keepalived.confの文法チェッカ
Haskell歴は4年
興味を持ったきっかけは、2005年のLLDNでsakai
さんの発表が全く意味不明だったこと
![Page 16: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/16.jpg)
4
内容は内容は
プログラミングモデルの話はすっ飛ばして
GHC 6.12.1の並列ランタイム性能改善の元となったと思われる論文”Runtime Support for Multicore Haskell”から
5分では時間がない(つっこまれると答えられない)ので要点を絞って
GHCのスレッドモデル
並列ランタイムの仕組み
最適化の試みを少しだけ
![Page 17: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/17.jpg)
5
GHCGHCのスレッドモデルのスレッドモデル
CPU #3CPU #2CPU #1CPU #0
CPU数と同数程度の
重いOSスレッド(worker threads)
軽いHaskellスレッド(OSスレッドの100x以上軽い)
とても軽いスパーク(sparks)
a `par` b
forkIO a
./a.out +RTS -N
![Page 18: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/18.jpg)
6
並列ランタイムの仕組み並列ランタイムの仕組み
CPU #3CPU #2CPU #1CPU #0
HaskellExecution Context #1
(HEC)
HEC #2 HEC #3 HEC #4
● An ownership field
● An message queue
● A run queue
● An allocation area
● GC remembered set
● A spark pool
● A worker pool
● An ownership field
● An message queue
...
... ...
![Page 19: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/19.jpg)
7
並列ランタイムの仕組み並列ランタイムの仕組み
CPU #0
HaskellExecution Context #1
(HEC)
● An ownership field
● An message queue
● A run queue
● An allocation area
● GC remembered set
● A spark pool
● A worker pool
Haskell Execution Context (HEC)
CPUごとに一つ作られる
+RTS -Nで指定する数だけ作られる
worker threadがHaskell threadを実行するのに必要なデータを持っている
“Capability”とか”virtual
processor”とも呼ばれる
- ownership fieldは、どのworker threadがcapabilityを持っているか(実行中か)
- message queueは、他のHECからの要求を受け取るためのキュー。たとえば”スレッドTを起こして!”というような具合
- run queueは実行準備ができているスレッドのキュー- allocation areaは、HEC固有のアロケーション領域。ヒープは一つを共有するけど、固有のもあるらしい。
- GC remembered setsは?- spark poolはa `par` bとするときのaのサンクが入る- worker poolはスペアのworker threadとforeign call用のプール
![Page 20: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/20.jpg)
8
並列ランタイムの仕組み並列ランタイムの仕組み
CPU #0
HaskellExecution Context #1
(HEC)
● An ownership field
● An message queue
● A run queue
● An allocation area
● GC remembered set
● A spark pool
● A worker pool
Haskellスレッドの実体はThread State Object
(TSO)というヒープに割り当てられたデータ構造
15 words + sizeof stack + αで小さい
run queueに入っているのをHECが順次round-
robinで実行していく
parで作られるsparkはspark poolに入る
システムの負荷が高くないときに、GCを生き延びた一部のsparkのみspark threadが作られ並列評価される
つまり必ず並列評価されるわけではない
![Page 21: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/21.jpg)
9
並列ランタイムの仕組み並列ランタイムの仕組み
CPU #0
HaskellExecution Context #1
(HEC)
● An ownership field
● An message queue
● A run queue
● An allocation area
● GC remembered set
● A spark pool
● A worker pool
HECのライフサイクル
message queueのメッセージを処理
run queueのスレッドを走らせる
spark poolにsparkが入っていればspark threadを起動し実行
HEC内でなくglobalな、black hole
poolをpollingして、いずれかのスレッドが実行できるようになったら実行
![Page 22: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/22.jpg)
10
最適化の例最適化の例
HEC間のspark poolの共有をpushモデルから、work stealing
queueというロックフリーなデータ構造を使うようにした
並列GCの改善
並列コピー式GCでimmutableなオブジェクトを扱うときは同期処理をしないように変更した
remembered setをHECごとに用意して局所性を高めた
ここでもwork stealing queueを使うことでGCのロードバランスをやめ、局所性を高めた
Control.Parallel.Strategiesを使うときに起こるメモリリーク問題を解消した
ThreadScopeが活躍したみたい
どのタイミングでどのHECが頑張っていたのか一目瞭然
![Page 23: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/23.jpg)
11
まとめというより所感まとめというより所感
純粋関数型は簡単に並列化できるとは言うものの実際に効率的なプログラムにするのは大変
ラインタイムをこつこつと計測して、こつこつとチューニング
GCなどに他の言語でも利用されている技術を適用
Strategy周りはもう少し勉強が必要
速度向上と環境整備でHaskellの並列プログラミングが一般的になっていくといいな
![Page 24: GHC 6.12.1 マルチコア対応ランタイムシステムについて](https://reader034.vdocuments.net/reader034/viewer/2022042602/55989cd61a28ab50288b4709/html5/thumbnails/24.jpg)
12
参考文献参考文献
Runtime Support for Multicore Haskell
(たぶん)GHC 6.12.1に取り込まれた改良に関する論文
Multicore Haskell Now! ACM Reflections
par/pseqを使った並列プログラミングに始まり、並行プログラミング、STM、データ並列までマルチコアを活用するための仕組みを一通り解説
サンプルコードが豊富
GHC Commentary
ちょっと情報が古いかもしれないけど参考になる