ホーム | 目次に戻る |
この記事ではライブラリの初期化、デバイスメモリの確保まで説明します。
なお、JCuda を利用したサンプルプログラムが GitHub にありますので、併せてご参照ください。
JCuda ライブラリを使用するには、以下のライブラリをインポートする必要があります。
import static jcuda.driver.JCudaDriver.*; import jcuda.*; import jcuda.driver.*;JCuda ライブラリの初期化コードを以下に示します。
// 例外を有効化する JCudaDriver.setExceptionEnabled(true); // CUDA ドライバを初期化 cuInit(0); // コンテキストを作成 CUcontext pctx = new CUcontext(); // Device(id=0: つまりデフォルト) の stream=0 をコンテキストに結びつける CUdevice dev = new CUdevice(); cuDeviceGet(dev, 0); cuCtxCreate(pctx, 0, dev); // PTX ファイルを読み込む String ptxfilename = preparePtxFile(CUFILENAME); CUmodule module = new CUmodule(); cuModuleLoad(module, ptxfilename);ここで preparePtxFile は .cu ファイルから .ptx ファイルを作成するための便利関数です。
ここまで来ると、module を使って .cu ファイル上 __global__ 宣言したエントリを取得することができます。
CUfunction entry = new CUfunction(); cuModuleGetFunction(entry, module, KERNELNAME); // 以降、entry を使用する。他の変数は解放して構わない。
型 | 対象クラス | バイト数 |
---|---|---|
BYTE | byte | 1 |
SHORT | short | 2 |
INT | int | 4 |
FLOAT | float | 4 |
LONG | long | 8 |
DOUBLE | double | 8 |
POINTER | Pointer | 8 |
CUdeviceptr devMemFloat = new CUdeviceptr(); cuMemAlloc(devMemFloat, Sizeof.FLOAT * SIZE);とします。ホストメモリは通常の Java のメモリ確保方法です。ホストメモリとデバイスメモリの間の転送は
// ホストメモリの確保 float[] hostMem = new float[SIZE]; // ホストメモリからデバイスメモリへの転送 cuMemcpyHtoD(devMemFloat, Pointer.to(hostmem), Sizeof.FLOAT * SIZE); // デバイスメモリからホストメモリへの転送 cuMemcpyDtoH(Pointer.to(hostmem), devMemFloat, Sizeof.FLOAT * SIZE);となります。
Pointer kp = Pointer.to(Pointer.to(input), Pointer.to(new int[]{size}), Pointer.to(output);とします。2つの点に注意してください。
extern "C" void kernel(float *input, int size, float *output);となります。
cuLaunchKernel(function, (SIZE + NTHREAD - 1) / NTHREAD, 1, 1, // Grid NTHREAD, 1, 1, // Block 0, null, // 共有メモリサイズ、使用 stream kp, null // カーネルパラメータ、拡張パラメータ(常に null) );