先日ビデオカードを買いました。GPUにAMD Radeon HD5670を積んだマルチディスプレイ対応で、マニュアル開いたままコードが書けて重宝しています。僕は3Dバキバキのゲームやらないし、グラフィクスには疎く絵心皆無なのでグラフィクスを多用したアプリケーションも書きません(DirectXなんか面白そうなんですけどね)。なので普段はせっかくのGPUがアクビしてます。HD5670にはプログラマブルシェーダー、ようは小さなCPUが400基も詰め込まれているらしいのですが、なんともMOTTAINAI。
ヒマを持て余しているようすのGPUに仕事をさせようと、OpenCLで遊んでみました。本稿ではOpenCL C++ Bindingによるマンデルブロ集合の計算を試みます。
OpenCL
GPUの計算性能は当然のことながらグラフィクス計算(そのほとんどがベクトルと行列演算)に使われているのですが、このパワーを汎用計算に使おうというのがGPGPU(General-Purpose computing on Graphics Processing Units)です。GPUの二大メーカー、NVIDIAとAMDはそれぞれ独自のGPGPUフレームワーク「CUDA」と「ATI Stream」をリリースしています。
CPUやGPU、さらにはCellプロセッサやDSPなどの計算デバイスのインタフェースを統一し、ソースコードレベルでの互換性をとることでこれらの混在したヘテロジニアスなマシン構成での計算デバイスを使用するオープンな標準規格がOpenCL(Open Computing Language)です。NVIDIA、AMDに双方とも、それぞれのGPGPUフレームワークをベースにしたOpenCLフレームワークをリリースしており、最近のGPUを搭載したビデオカードであればOpenCL環境を構築できます。
SDKのインストール(ATI Streamの場合)
ATI Stram SDKのページからSDKと最新のドライバをダウンロード、インストールすれば準備はあっけなく完了します。開発環境はVisual Studio 2010 Professional以上となっていますが、Express Editionでも問題はなさそうです(ただし、サンプルコードのソリューション中、いくつかのプロジェクトがオープンに失敗するようですが)。
ATI Stream SDKをインストールすると環境変数ATISTREAMSDKROOTが設定されます。各プロジェクトのプロパティで、
インクルード・パス: "$(ATISTREAMSDKROOT)include" ライブラリ・パス: "$(ATISTREAMSDKROOT)lib\x86" (32bit) "$(ATISTREAMSDKROOT)lib\x86_64" (64bit) 追加のライブラリ: OpenCL.lib
をセットしてください。また、実行時にはOpenCL.dllを必要としますがSDKのインストール時に適切なディレクトリ(\Windows\System32, \Windows\SysWOW64)に配置されているようです。
OpenCL C++ Bindings
OpenCLを触るのは今回が初めてでして、大きな書店に走って入門書を一冊手に入れてきました。OpenCLは各計算デバイス上で実行されるコードを「OpenCL C」で記述し、計算デバイスを利用するホスト側はOpenCLが用意したC-APIを呼び出すことで計算デバイスを制御します。入手した入門書にもC-APIを使ったサンプルが並んでいました。
一方、OpenCL規格のまとめ役であるKhronos GroupはC-APIにクラスの皮をかぶせたC++ Bindingsも提供しており、C-APIを裸で使うよりずっとコンパクトに表現できます。C++ Bindingのドキュメント(PDF)首っ引きで入門書にあったサンプルをC++にportしてみたところ、400行のCコードが100行足らずで書けました。
手を染めて間もないOpenCLではありますが、以降OpenCLおよびOpenCL CとC-APIの詳細については入門書や解説書、Khronos Groupあるいは各ベンダのドキュメントに譲ることにして、「C++ BindingによるOpenCLの遊び方」について語ることにします。