管理人はMATLABで研究活動をしとりますが、結構ヘビーな処理がしばしば。
そこで、nvidiaの最近のグラボがあれば使えるCUDAを使って高速化したい!というわけで、MATLAB+CUDAのとっかかりを。毎度のことですが、バグとかは責任をおいませんよ。
なお、私はプログラマレベル0.2(当社比)な初心者なので、で間違ってても石を投げないでください(汗
でも、その分初心者でもわかる内容にしたい!とおもいます。
1.CUDAの準備
- nvidiaのGeforce8xxx、9xxxとか、280,260とかのCUDA対応ボードを買って、パソコンにいれておく。なくてもできるけど、ソフトウェアエミュレーションは激遅い^^;
- Visual Studio2005等、CUDAのコンパイルに使える環境のインストール。私はVS2005でやってますが、windowsSDKがあればexpressでもいけるかな??詳しくはCUDAのサイトで確認してくださいな。たぶん2003か2005くらいしか対応していなかった気もしますが・・・
- CUDAのSDK、ツールキット、ドライバのインストール。nvidiaのサイト(http://www.nvidia.co.jp/object/cuda_get_jp.html)からダウンロードし、インストール♪これは簡単ですよね??
- サンプルがコンパイルできればOK!なお、ボードがない場合にはビルドのターゲットをエミュレーションにして実行すればいちおう実行できますよ。
2.MATLABの準備
- MATLABのインストール(当たり前ですねw) 注!->MATLAB2009aでは失敗することが!下のコメントに対処法を記しときます.
- MEXファイルがコンパイルできるかチェック。私はMATLAB Compilerを持っているので、mbuild -setup、もしなければmex -setupで使用するコンパイラを設定する。MATLAB付属のlccでは、私はCUDAコードをコンパイルするまでうまく設定できませんでした。上級者ならできるかもしれません??とりあえず、VS2005のほうが簡単にできたので、VS2005のコンパイラを選びます。
- とりあえずこれだけかな?mexのサンプルを用意してみて、コンパイルできればOK!
3.CUDA入りmexファイルでMATLABを加速!
- MATLAB+CUDAに必要となるスクリプト等をnvidiaのサイト(http://www.nvidia.co.jp/object/matlab_cuda_jp.html)から落としてきます。
- Matlab_CUDA-1.1a.zipを解凍し、中のbinの中にあるnvmex.plを、MATLABのインストールフォルダのbinフォルダに入れる。MATLABの場所がよくわからなければMATLABのショートカットのリンクからたどってください。
- nvmex.mと、nvmex-helper.m、nvmexopts.batがCUDAを使ったmexのコンパイルに必要だと思われます。パスの設定とかよくわからなければ、コンパイルしたいファイルと一緒のフォルダにおいてください。
- いよいよ本題!CUDA de MEX in MATLABですよ!私は小難しいことはわかりませんので、ここにある(http://www.nvidia.co.jp/object/matlab_cuda_jp.html)ホワイトペーパー内のサンプルをオススメします。なんともわかりやすい!でも、さすがにそれではアレですので(というか、pdf、一部文字がきれてますがな。nvidiaさん)、2乗ではなく配列の各要素の対数を求めるサンプルcuda_test.cuをおいておきます。一行しか変わってないですがw
- あとは、思う存分CUDAプログラミング!サンプルをみればMATLABとのデータやりとりの方法は推して量れるかと。必要なデータをGPU上に転送して・・・いざ並列コンピューティング!
- mexファイルのコンパイルには、MATLAB上で,[nvmex -f nvmexopts.bat cuda_test.cu -IC:\cuda\include -LC:\cuda\lib -lcudart]とします。
- 思い通りの処理をつんで、”がんばって”高速化してください!
注意!私の環境では,上記nvmex コマンドを実行しても,コンパイルができませんでした.それは,user32.dll,gdi32.dllなど,WindowsSDK?に含まれているらしきライブラリがない旨のエラーが出ました.そこで,nvmexopts.batに含まれるコンパイルオプションの設定部分
set LIB=%VCINSTALLDIR%\ATLMFC\LIB;%VCINSTALLDIR%\LIB;%VCINSTALLDIR%\PlatformSDK\lib;%VSINSTALLDIR%\SDK\v2.0\lib;%MATLAB%\extern\lib\win32;%LIB%;
の部分を,
set LIB=%VCINSTALLDIR%\ATLMFC\LIB;%VCINSTALLDIR%\LIB;%VCINSTALLDIR%\PlatformSDK\lib;%VSINSTALLDIR%\SDK\v2.0\lib;%MATLAB%\extern\lib\win32;%LIB%;C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib;
に書き換え,ライブラリパスを追加することでコンパイルができました.本当はどうするんでしょう??windowsSDKのインストールの仕方が悪かったんですね,きっと.
↑VS2005 Expressでやったときのでした。VS2005なら大丈夫だった!記憶違い^^;
高速化にはさまざまなテクニックと知識が必要ですが・・・くわしくはCUDAサンプルを読んでくださいwSIMD的演算ならす~ぐに簡単並列化!大規模データもへっちゃら!(というほど簡単ではないかもですが汗
ちなみに、普通に小さな行列の掛け算やら要素ごとの演算をするくらいならMATLABだけでやったほうがだいぶ高速です。グラボへのデータ転送遅いし、MATLABはdouble、CUDAはfloatなので変換などのオーバーヘッドも無視できない。データ量が比較的すくなくて、計算コストが高く、並列化できる処理。そういうのだけにしたほうがいいっスヨ。ちなみに、float精度でよければ、上のlogとるサンプルはMATLABでやるよりCUDAでやったほうが高速でした。(Geforce8400GSのへなちょこボードですら!)
以下、高速化のコツ??まぁ、できたら。ですが。あまり詳しくないので信じないでください。
- スレッドをサボらせない。データ長より長い部分はしゃあないか。
- 繰り返し使うデータは共有メモリにいれましょう。
- メモリアクセスはワープ単位(16ないし32スレッド)でアドレスが連続になるようにしたほうがよさげ。バス幅いっぱいに使いましょう。
- メモリのバンクが衝突しないように。これ、意外と難しいきもする。
- if文少なく。%とかも遅いらしい。複雑な演算ももちろん減らそう。そもそもアルゴリズムが遅かったら意味ナイね。
- 同期命令を極力すくなく。これ、だいぶ遅いです。
ほかにもいろいろあったり例外もあったり・・・ 完全な高速化は私にはあまりに難しいのでヘルプを読んでCUDAさい。MATLABより早くなればヨシ、ですよw(MATLABもそもそもベクトル演算そこそこはやいしね^^;)
高速化のためにはいかにグラボにデータを載せっぱなしにするかが大事ですが,
MATLABのmexでする例を,快適計算ライフ3にてご紹介しましょう.
本日の来訪者: -
昨日の来訪者: -
来訪者累積: -
- > まーぼうさん 書き込みありがとうございます!私も初心者でわからないことだらけなので随時情報交換しましょう! -- 管理人 (2010-08-19 15:29:20)
- メーリングリスト投稿ありがとうございます。
さっそくですが、MATLABのやつは現在設定など
いろいろ大変なことがあります。
わかんなかったら、MLにて質問します。
では。 -- まーぼう (2010-08-06 18:17:12)
- 上の2009aでコンパイルできない問題を回避するその場しのぎ的方法をCudaフォーラムで発見.
MATLABのbinに入れるnvmex.plの中身,728行目辺りを,
$main::temp_dir = mexCatdir($ENV{'TEMP'},tool_name() . "_" . uuidgen());
から
$main::temp_dir = mexCatdir($ENV{'TEMP'},tool_name() . "_" . "xxx");
に変更し,UUIDを使わず適当な名前にしてやると.なんか問題でるかもしれないけど,とりあえずはコンパイルできそうです.
-- 管理人 (2010-03-24 03:01:07)
- 2009aでコンパイルできない原因は,2007bではmexutils.pmにあったuuidgenが,2009aではmexutils.pmから削除されていることにありそう.
ただ,win32::APIを導入する方法がわからず断念.管理人はperlをやったことがなく,ちょっと無理でした.
perl詳しい方,直し方おしえてくらさい… -- 管理人 (2010-03-24 02:27:55)
- その後,MATLAB2009aで試してみたら,"Undefined subroutine &main::uuidgen called atほげほげ"と出てなぜかコンパイルできない…
2007bでは相変わらずできるので,何か設定ミスらしいのですが…なんでかな??
perlスクリプトのあたりがおかしいらしい… -- 管理人 (2010-03-24 01:49:49)
最終更新:2010年08月19日 15:29