2010年1月9日土曜日

GotoBLAS だと Matlab からスレッド数を変更できない

今日は Matlab から GotoBLAS/ATLAS の dgemm を呼び出したらどうなるかをチェック。
コンパイルなどは特に問題なくできる。

ただ、Matlab の maxNumCompThreads に設定されているスレッド数を GotoBLAS に渡すことができないようだ。
実際にやっているのは、Matlab の中で、

setenv('OMP_NUM_THREADS','8');
setenv('GOTO_NUM_THREADS','8');
とすると、Matlab から mex を呼んでいるときに mex の中では両方とも環境変数として設定されているのだが、ここから libgoto2.a の関数を呼ぶときに伝わっていないようだ。ここで

$ nm mexDgemm.mexa64 | grep dgemm
とすると、

0000000000001b00 t dgemm_
の行があるので、すでに組み込まれているはずだが、ひょっとしたら、この中では OMP_NUM_THREADS を認識できないのかもしれない。

そういえば、mex でコンパイルするときに(内部で g++ を利用)、
-L(path) -lgoto2
だと、export LD_PRELOAD で指定しないとダメだったが、
(path)/libgoto2.a
だと、LD_PRELOAD を指定しなくてもOKだった。
このあたりとも影響があるのかもしれない。

ただし、Matlab を起動する前にコマンドラインで OMP_NUM_THREADS を指定すると、きちんと反映される。

以下は、行列のサイズを変更したときの dgemm のスピードの違い(単位は秒)。なお、
n: 行列のサイズ
th: スレッド数
Matlab: Matlab で普通に C0 = alpha*A*B + beta*C を実行
mwblas: Matlab にある blas を mex 経由で直接利用
プロセッサは、Xeon E5520 (2.27GHz) x2 でメモリは24GB
になっている。









dgemm スピードの違い
n th Matlab mwblas GotoBLAS2 ATLAS
6000 1 65.70 65.09 45.98 7.20
6000 8 9.11 8.69 19.94 7.23
10000 8 41.55 40.04 27.85 34.38
20000 8 332.43 327.77 258.81 308.74


どうやら、ATLAS は OMP_NUM_THREADS も無視して 8threads で計算するようだ。(libptf77blas.aはそうなのかもしれない。)
あと、行列が大きくなると、GotoBLAS が速くなるのがわかる。ただし、n=6000で 8スレッドが遅いのが不思議だ。

いずれにしても、GotoBLAS/ATLAS のスレッド数を maxNumCompThreads と連動できないとなると、SDPA-M で GotoBLAS/ATLAS に接続するのは難しいかもしれない

今日の作業内容: Matlab チェック
今日のBGM: NOIR OST [1-2]
明日の予測作業時間: 4h

4 件のコメント:

  1. 変だな、と思ったら原因を調べましょう。それが研究。

    スレッドの動的な変更は環境変数では無理です(やっても構わないが性能が悪くなる)。直接内部関数を呼び出す必要があります。

    n=6000, th=1 の時に 45.98sec ということなので理論値に対する効率は 103.4% になります。Turbo Boost が効いているので正確は測定は無理ですね。やり直しましょう。

    n=10000,20000 ではそれぞれ 85.1%, 98.8% になります。これも変ですね。

    本当の値は Turbo Boost off 時に 96% 弱くらいになるはずです。

    返信削除
  2. GotoBLAS ですと、スレッドの動的な変更は難しいんですね。スレッド数を変化できる Matlab の内部がどうなっているかよく解かりませんが、性能を少し犠牲にしているのかもしれないですね。

    あと、Turbo Boost ははじめて知りました。今どきの設定ですと標準で使用できるようなので(買ったときのプリインストールの RHEL がそのままなので)、むしろユーザとしては Turbo Boost が効いている状態でどれだけ性能が出るか、ってなりそうです。
    時間は Matlab の tic, toc で計測していますが、tic,toc が Turbo Boost に完全に対応し切れていないこともありえます。

    とりあえず、時間ができたときに Turbo Boost の ON/OFF をどうやって切り替えるか調べてみます。

    返信削除
  3. 環境変数というのはグローバル変数の一種なのでスレッドセーフを保つことができなくなる。というわけで実装としては良くない。代わりに

    void goto_set_num_threads(int nthreads);

    という関数を用意してあるのでこれを呼び出せばスレッド数を動的に変更できる(Windows 向けはまだ実装していない)。-1 を与えるとディフォルトのスレッド数に戻すことが可能。だだ、この関数は export されていないので shared library を構築して使用する場合には別途指定が必要。

    TurboBoost は一般ユーザには良いのだろうけど、開発者・研究系では邪魔になるだけ。最初は off にして動作確認を行ってから、最後のベンチマークの時だけ on にすべし。

    返信削除
  4. うーん、環境変数も使い勝手がいろいろとあるもんなのですね。
    goto_set_num_threads も今度調べてみます。

    あと、TurboBoost の on/off は、ちょっと難しいです。自分だけで使っているコンピュータではないので、勝手に on/off してしまっていいものなのか、自分だけでは判断できないところです。

    返信削除