gpuのついたパソコンを買った。
簡単なfor文をぶん回して性能を試したくなったので、モンテカルロの円周率計算で実行時間を比較した。
言語はpythonを使用。
gpuアクセラレーションの知識はほぼないのでNumbaの乱数生成ページにあったコードで実行。(https://numba.pydata.org/numba-doc/0.33.0/cuda/random.html)
その際にgpuの占有率が低いという警告文が気になったので
(スレッド数, ブロック数)=(512, 128)
に変更した。
結果は下図の通り
横軸のpowerは計算回数の常用対数。
凡例はアノテーションに倣った。
normalはアノテーションを何もつけていないパターン。
注意点としてgpuアクセラレーション(cuda.jit)では
(反復回数)= (計算回数) /((スレッド数)*(ブロック数))
としたため、power < 6 では常に反復数が1になっている。
要は全くあてにならない。
計算結果について(上グラフ)
乱数生成は
gpuアクセラレーション:xoroshiro128p_uniform_float32()
それ以外:random()
を使った。
乱数生成の方法が違うため、誤差率のグラフはそんなもんだよな、といった感じ。
- アノテーションをつけないパターンの誤差率が妙に小さい。
- njitのパターンだけ誤差率が大きい。
ここらへんは何かの意味がありそう。しかし詳しくないのでなにも言えない。
乱数生成に時間が使われていて並列化すると値が偏る、とかあるのだろうか。
randomの中身やjitの仕組みをしっかり勉強しないとダメそう。
計算時間について(下グラフ)
アノテーションをつけるだけでかなり速くなる。
pythonはnumpyの行列計算にしないと全部遅いと思っていたので驚いた。
また、gpuアクセラレーションもオフロードのオーバーヘッドでもっと遅いと思っていた。
gpuアクセラレーションの高速化をざっくり計算すると、アノテーションなしの場合と比べて2500倍以上だった。すごい
(アノテーションなしのforループが遅すぎる気もする)
njitの場合と比べても10倍以上であり、値段が高いだけあるなと思った。
6→7で計算時間の伸びが緩やかなのは反復回数が少ないためにオーバーヘッドが大きくなったのだろうか。
まとめ
- アノテーションをつけるだけでかなり計算が速くなって驚いた
- gpuはやっぱり速い
- 勉強不足
情報系の知識があればもっと楽しめたと思う。ちょっと悔しい。
gpuアクセラレーションは、なんか裏でうまいことやってくれるんだろうな、と思っていた。
しかしある程度勉強しないと手軽には使えなさそう。
いま積んでる本消化したら並列計算の勉強をしてみたいなと思いました。
以上