Upload
mitsutoshi-aoe
View
1.782
Download
5
Embed Size (px)
DESCRIPTION
2009年Haskell忘年会前哨戦
Citation preview
GHC 6.12.1GHC 6.12.1マルチコア対応ランタイムシステムマルチコア対応ランタイムシステム
についてについて
id:maoe
id:maoeid:maoe
青江光敏http://d.hatena.ne.jp/maoe/
http://github.com/maoe
Keepalived.confの文法チェッカ
Haskell歴は4年
id:maoeid:maoe
青江光敏http://d.hatena.ne.jp/maoe/
http://github.com/maoe
Keepalived.confの文法チェッカ
Haskell歴は4年
興味を持ったきっかけは、2005年のLLDNでsakai
さんの発表が全く意味不明だったこと
内容は内容は
プログラミングモデルの話はすっ飛ばして
GHC 6.12.1の並列ランタイム性能改善の元となったと思われる論文”Runtime Support for Multicore Haskell”から
5分では時間がない(つっこまれると答えられない)ので要点を絞って
GHCのスレッドモデル
並列ランタイムの仕組み
最適化の試みを少しだけ
GHCGHCのスレッドモデルのスレッドモデル
CPU #3CPU #2CPU #1CPU #0
CPU数と同数程度の
重いOSスレッド(worker threads)
軽いHaskellスレッド(OSスレッドの100x以上軽い)
とても軽いスパーク(sparks)
a `par` b
forkIO a
./a.out +RTS -N
並列ランタイムの仕組み並列ランタイムの仕組み
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
...
... ...
並列ランタイムの仕組み並列ランタイムの仕組み
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”とも呼ばれる
並列ランタイムの仕組み並列ランタイムの仕組み
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が作られ並列評価される
つまり必ず並列評価されるわけではない
並列ランタイムの仕組み並列ランタイムの仕組み
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して、いずれかのスレッドが実行できるようになったら実行
最適化の例最適化の例
HEC間のspark poolの共有をpushモデルから、work stealing
queueというロックフリーなデータ構造を使うようにした
並列GCの改善
並列コピー式GCでimmutableなオブジェクトを扱うときは同期処理をしないように変更した
remembered setをHECごとに用意して局所性を高めた
ここでもwork stealing queueを使うことでGCのロードバランスをやめ、局所性を高めた
Control.Parallel.Strategiesを使うときに起こるメモリリーク問題を解消した
ThreadScopeが活躍したみたい
どのタイミングでどのHECが頑張っていたのか一目瞭然
まとめというより所感まとめというより所感
純粋関数型は簡単に並列化できるとは言うものの実際に効率的なプログラムにするのは大変
ラインタイムをこつこつと計測して、こつこつとチューニング
GCなどに他の言語でも利用されている技術を適用
Strategy周りはもう少し勉強が必要
速度向上と環境整備でHaskellの並列プログラミングが一般的になっていくといいな
参考文献参考文献
Runtime Support for Multicore Haskell
(たぶん)GHC 6.12.1に取り込まれた改良に関する論文
Multicore Haskell Now! ACM Reflections
par/pseqを使った並列プログラミングに始まり、並行プログラミング、STM、データ並列までマルチコアを活用するための仕組みを一通り解説
サンプルコードが豊富
GHC Commentary
ちょっと情報が古いかもしれないけど参考になる
1
GHC 6.12.1GHC 6.12.1マルチコア対応ランタイムシステムマルチコア対応ランタイムシステム
についてについて
id:maoe
2
id:maoeid:maoe
青江光敏http://d.hatena.ne.jp/maoe/
http://github.com/maoe
Keepalived.confの文法チェッカ
Haskell歴は4年
3
id:maoeid:maoe
青江光敏http://d.hatena.ne.jp/maoe/
http://github.com/maoe
Keepalived.confの文法チェッカ
Haskell歴は4年
興味を持ったきっかけは、2005年のLLDNでsakai
さんの発表が全く意味不明だったこと
4
内容は内容は
プログラミングモデルの話はすっ飛ばして
GHC 6.12.1の並列ランタイム性能改善の元となったと思われる論文”Runtime Support for Multicore Haskell”から
5分では時間がない(つっこまれると答えられない)ので要点を絞って
GHCのスレッドモデル
並列ランタイムの仕組み
最適化の試みを少しだけ
5
GHCGHCのスレッドモデルのスレッドモデル
CPU #3CPU #2CPU #1CPU #0
CPU数と同数程度の
重いOSスレッド(worker threads)
軽いHaskellスレッド(OSスレッドの100x以上軽い)
とても軽いスパーク(sparks)
a `par` b
forkIO a
./a.out +RTS -N
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
...
... ...
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用のプール
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が作られ並列評価される
つまり必ず並列評価されるわけではない
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して、いずれかのスレッドが実行できるようになったら実行
10
最適化の例最適化の例
HEC間のspark poolの共有をpushモデルから、work stealing
queueというロックフリーなデータ構造を使うようにした
並列GCの改善
並列コピー式GCでimmutableなオブジェクトを扱うときは同期処理をしないように変更した
remembered setをHECごとに用意して局所性を高めた
ここでもwork stealing queueを使うことでGCのロードバランスをやめ、局所性を高めた
Control.Parallel.Strategiesを使うときに起こるメモリリーク問題を解消した
ThreadScopeが活躍したみたい
どのタイミングでどのHECが頑張っていたのか一目瞭然
11
まとめというより所感まとめというより所感
純粋関数型は簡単に並列化できるとは言うものの実際に効率的なプログラムにするのは大変
ラインタイムをこつこつと計測して、こつこつとチューニング
GCなどに他の言語でも利用されている技術を適用
Strategy周りはもう少し勉強が必要
速度向上と環境整備でHaskellの並列プログラミングが一般的になっていくといいな
12
参考文献参考文献
Runtime Support for Multicore Haskell
(たぶん)GHC 6.12.1に取り込まれた改良に関する論文
Multicore Haskell Now! ACM Reflections
par/pseqを使った並列プログラミングに始まり、並行プログラミング、STM、データ並列までマルチコアを活用するための仕組みを一通り解説
サンプルコードが豊富
GHC Commentary
ちょっと情報が古いかもしれないけど参考になる