CUDA memo (3) aobenchをCUDAで実装。
aobenchという上記画像を吐くプログラムがあります。オリジナルのC言語ソースコードは
http://code.google.com/p/aobenchcl/source/browse/#svn/trunk/ao/c_reference
などに。で、このプログラムが色々な言語で実装したりして速度を競うのが流行った時期がありました。似た様なプログラムにsmallptというものもあります。これらのプログラムはどちらも出力対象のデータ(画像)の要素(ピクセル)ごとの並列性が高い(とあるピクセルの色を求めるために、前のピクセルの値などが必要ない)ので、CUDAなどの並列性の高いアーキテクチャに圧倒的に向いています。
というわけでaobenchをCUDAに移植してみました。以下の256x256の画像がその出力結果です。
元のC実装は約1.42秒、CUDA実装は約0.11秒。画像サイズを2x2から256x256から変化させた場合の実行時間の変化もグラフにしてみました。
縦軸は秒、横軸はピクセルの数です。なんともまあわかりやすい。512以降はなんかCUDA側をちゃんと動かせなかったので256まで。ソースコードは全部githubに。
http://github.com/hogelog/cuda_learn
環境は以下のとおり。
- Device: GeForce 9600 GT
- PCI: PCI Express 2.0
- Toolkit: CUDA Toolkit for Ubuntu Linux 9.10 release 3.1 (June 2010)
- OS: Ubuntu 10.04.1 LTS, 2.6.32-24 i686
- CPU: Intel(R) Core(TM) i7 CPU 960 @ 3.20GHz
- CPU Cache: 8192 KB
- Memory: 2517 MB
CUDA移植する際に
- CUDAにはdrand48などの擬似乱数生成器がないためthrustライブラリ(http://code.google.com/p/thrust/)を利用。
- doubleを全てfloatに。
- コンパイルオプション-use-fast-math利用
- constant メモリ領域の利用(__constant__変数フラグ)
- 出力画像形式をPFM 形式に変更(生のfloat 値のラスタ画像形式)
とかそんなことも一応変更。
GPU(CUDA)はすごい?
元のC実装は叩き台とするための簡単な実装。CPUで動作する実装と比較するというならばせめてOpenMPやTBBなんかで並列化されたプログラムと比較するべきだろうなと思う。やってない。CUDAに移植するより圧倒的に楽だと思う。
参考
CUDAでAO bench - imHo
既にid:mokeheheさんが通った道でもあります。擬似乱数生成器が無くて苦労されてるようですが、今はthrustライブラリにあるから楽チンですね。