Matlabのparfor
Matlab 2008aからParallel Computing Toolboxにfor loopを並列化して処理速度の向上をさせるための
parfor - end
と言う命令が加わったのだが、最近ようやくちゃんと使ってみた。
以前にも使った事はあるのだが、並列化してもCPU使用率が上がらなかったので、並列化してへんやんと思っていたのだが(その時はtictocで計算時間をちゃんと比べなかった)、実はparforを使う前の設定がまずかったようだ。以前はメモリー64Gのサーバーを使っていたので、手動並列化(単にスクリプトを分割して2プロセス走らせただけw)でごまかしていた。
今使ってるクライアントの構成は
Ubuntu 9.04 x86
Core2Quad 9550
Memory 4G
Matlab 2009a
と通常のデスクトップに勝手にUbuntuを入れただけなので、メモリーの制約の為に手動並列化が使えない。そんな理由でちょっと真面目にparforの使い方を勉強することになった。
以前ちらっとドキュメントを斜め読みした時にはforの前にparをつけてparforにするだけで良いと勘違いしていたのだが、parforを使うときには、parforの前に
matlabpool
と言う並列化をさせる為の環境を呼び出す関数を入れる必要がある。
これを呼び出さないと、parforが使えない。すなわち並列化が行われないと言う訳だ。
matlabpoolは開始するときは引数を入れなくても、4コアまでならば自動的にCPUのコア数で設定してくれる。(5コア以上は対応していないみたい?)で並列処理が終了したら
matlabpool close
で並列処理を終了させる。
並列処理中のプロセスがどうなっているのかをみた所
こんな感じで、並列処理をしている分だけmatlabのプロセスが走っているようだ。
ちゃんとtictocで時間を計ってみると半分位の時間で計算されているようだ。
まとめると
matlabpool
parfor i = x:xx
{statement}
end
matlabpool close
と言う感じ。
あと、parforを使うためにはparfor内の変数の扱い方に色々とルールがあってこれが面倒。
とりあえず、自分が引っかかったポイントをいくつか。。
- parfor loopのインデックスは整数で一つずつ増加させる
parfor i = 1:10
はOKだが、
parfor i = 10:-1:1
parfor i = 1:0.1:2
parfor i = 1:2:10
などは禁止
- growing variableは禁止される事が多い(OKの場合もある)
計算の結果を代入していく変数などはzeros等を使って、始めに空間を確保しておく
- parfor外の変数をparfor内でupdateさせない
parfor外で定義した変数をparfor内でupdateさせようとするとエラーが返ってくる
parfor内で新しい変数に代入してからparfor外でまとめた方が良いらしい。
(1月14日追記)
parfor内の計算がそこそこ時間のかかるものだと、parforを使った方が早くなるが、parfor内の計算が一瞬で終わるようなものの場合、parforを使った方がむしろ遅くなるようだ。