以前 Aparapi を NetBeans に組み込んでお手軽に Java で GPGPU 演算をしたりしましたが、やはり CUDA が使いたくなりました。Java プログラムなのにプラットフォーム依存性を持ってしまうことは残念ですが、 JCuda(CUDA の Java 版)であれば、C 言語で書いた CUDA 用のカーネルをそのまま再利用できるので、便利です。ここに、NetBeans で JCuda が使えるようになるまでのメモ書きを残します(OS は Windows 8.1)。
1. Visual Studioのインストール
C で記述された CUDA ファイル(.cu)をコンパイルするために、Visual Studio をインストールします。
私は Visual Studio Professional 2013 をインストールしましたが、https://www.visualstudio.com/ja-jp/downloads/download-visual-studio-vs から、Community や Express 版をインストールすれば十分に思います。
インストールが完了したら、Visual Studio に付属する C コンパイラ「cl.exe」が置かれたフォルダへの環境変数パスを通します。Visual Studio 2013 の場合、「C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin」となります。
以下に、環境変数パスを通す手順の一例を記載しておきます。
1. コントロールパネル(スタートアイコンを右クリック、あるいはチャーム→設定等から)を開き、「システム」を選択。
2. システム画面左側の「システムの詳細設定」を選択。
3. システム環境変数の変数名 Path を選択し、「編集」ボタンを押す(無ければ「新規」ボタン)。
4. セミコロンで区切って、「cl.exe」が置かれたフォルダのパスを記載する。
2. CUDA Toolkitのインストール
続いて、CUDA Toolkit をインストールします。
NVIDIA 公式のダウンロードページ(https://developer.nvidia.com/cuda-toolkit-archive)にアクセスし、最新版の Toolkit をダウンロードします(2015年6月21日段階で、version 7)。最新の CUDA Toolkit が、必ずしも最新の JCuda に最適なバージョンというわけではなさそうですが、とりあえず最新版にしておきます。
CUDA Toolkit 7 のダウンロードが終わったら、インストールを行います。途中出てくる選択肢は「高速インストール」にしておけばよいと思いますが、容量が不安であったり今回使うもの以外はインストールしたくない方は、「カスタムインストール」で「Toolkit」と「Developer Drivers」だけを選択すると良いと思います。
3. JCuda のダウンロード
次に、JCuda をダウンロードします。
JCuda 公式のダウンロードページ(http://www.jcuda.org/downloads/downloads.html)にアクセスし、お使いの環境に合った Binaries をダウンロードし、解凍します。
ここでは「Binaries for Windows 64bit」で話を進めていきます。
zip ファイルを解凍すると色々と便利そうなものが詰まっていますが、今回は以下の 3 つのファイルだけを使います。
・jcuda-0.7.0a.jar
・JCudaDriver-windows-x86_64.dll
・JCudaRuntime-windows-x86_64.dll
「JCudaDriver-windows-x86_64.dll」と「JCudaRuntime-windows-x86_64.dll」の 2 つのファイルは、「C:\Windows\System32」の中に入れます。「jcuda-0.7.0a.jar」は適当なフォルダで構いません。
4. NetBeans で動かしてみる
最後に NetBeans で動かすことができるか、テストします。プロジェクトに JCuda ライブラリを読み込ませましょう。
プロジェクトウィンドウから、「ライブラリ」を右クリックして、「JAR/フォルダの追加」を選択し、先ほど保存した「jcuda-0.7.0a.jar」を読み込ませます。あるいは、様々なプロジェクトで使う可能性がある場合は、「ライブラリの追加」→「作成」と進み、JCuda をライブラリとして登録しておきます。
公式サイトのサンプルを実行してみましょう。NetBeans 上で「JCudaVectorAdd.java」と「JCudaVectorAddKernel.cu」を作成し、「JCudaVectorAdd.java」をコンパイルして実行します。すると nvcc が起動し、「JCudaVectorADdKernel.ptx」が生成され、それが Java 上から呼び出されます。
GPU 上のメモリの確保やメモリの受け渡し、カーネルの呼び出し等は Java で記述されていますが、コードは見ての通り、大体 C と似たような感じで分かりやすいです。実行に成功すると、以下のような結果が出力されます。
Executing
nvcc -m64 -ptx [KernelName].cu -o [KernelName].ptx
Finished creating PTX file
Test PASSED
float の足し算を Java 上と GPGPU 上でそれぞれ 100000 回行い、結果の差が全て 10^-5 以下であれば「Test PASSED」が表示される内容となっています。
私は JCuda を使うことで、約 50 分かかっていた三次元逐次近似再構成が、30 秒以内で終わるようになりました。
およそ 100 倍の高速化になります。