Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

CUDA コードを含む MEX 関数の実行

CUDA コードを含む MEX ファイルの作成

他の MEX ファイルと同様に、CUDA® コードを含む MEX ファイルにも mexFunction と呼ばれる単一のエントリ ポイントがあります。MEX 関数には、MATLAB® から gpuArray オブジェクトと交信し、CUDA コードを起動するホスト側のコードがあります。MEX ファイルの CUDA コードは CUDA runtime API に準拠していなければなりません。

MEX ファイルの起動に際しては、関数 mxInitGPU を呼び出す必要があります。これにより、GPU デバイスが適切に初期化され、MATLAB に認識されます。

gpuArray オブジェクト用の MEX ファイルの作成に使用するインターフェイスは、標準 MATLAB 配列用の MEX インターフェイスとは異なります。

CUDA コードを含む MEX ファイルの例は、以下を参照してください。

このファイルには、以下の CUDA デバイス関数が含まれています。

void __global__ TimesTwo(double const * const A,
                         double * const B,
                         int const N)
{
    int i = blockDim.x * blockIdx.x + threadIdx.x;
    if (i < N)
        B[i] = 2.0 * A[i];
}

このファイルに含まれる以下の行では、配列のサイズを決定し、適切なサイズのグリッドを起動します。

N = (int)(mxGPUGetNumberOfElements(A));
blocksPerGrid = (N + threadsPerBlock - 1) / threadsPerBlock;
TimesTwo<<<blocksPerGrid, threadsPerBlock>>>(d_A, d_B, N);

結果として得た MEX 関数の実行

次の例では、MEX 関数は入力配列の各要素に 2 を乗算し、その値を出力配列に収めます。これをテストするため、すべての要素が 1 の gpuArray から始めます。

x = ones(4,4,'gpuArray');
y = mexGPUExample(x)
y = 

    2    2    2    2
    2    2    2    2
    2    2    2    2
    2    2    2    2

入力配列も出力配列も gpuArray オブジェクトとなります。

disp(['class(x) = ',class(x),', class(y) = ',class(y)])
class(x) = gpuArray, class(y) = gpuArray

CUDA カーネルとの比較

Parallel Computing Toolbox™ では CUDAKernel オブジェクトもサポートされており、CUDA コードの MATLAB との統合に使用できます。CUDAKernel オブジェクトは、CU ファイルと PTX ファイルを使用して作成できます。一般的には、CUDAKernel オブジェクトを使用するよりも、MEX ファイルを使用するほうが柔軟性が高くなります。

  • MEX ファイルには、NVIDIA® Performance Primitives (NPP) ライブラリや cuFFT ライブラリなど、NVIDIA ライブラリを含むホスト側ライブラリの呼び出しを含めることができます。MEX ファイルには、ホストから CUDA ランタイム ライブラリ内の関数への呼び出しを含めることもできます。

  • MEX ファイルでは、C または C++ コードから、入力サイズを解析して異なるサイズのメモリを割り当て、異なるサイズのグリッドを起動することができます。これに対し、CUDAKernel オブジェクトを呼び出す MATLAB コードでは、出力メモリを事前に割り当ててグリッド サイズを決定しなければなりません。

複素数データへのアクセス

GPU デバイスでの複素数データは、実数部と虚数部がインターリーブされた形式で格納されます。つまり、複素数 gpuArray A の場合、要素 i の実数部と虚数部が連続したアドレスに格納されることになります。MATLAB は CUDA の組み込みのベクトル型を使用して、複素数データをデバイスに格納します (『NVIDIA CUDA C Programming Guide』を参照)。

カーネルでの必要性に応じて、複素数データへのポインターは実数型または組み込みのベクトル型としてキャストできます。たとえば、MATLAB で次の行列を作成するとします。

a = complex(ones(4,'gpuArray'),ones(4,'gpuArray'));

gpuArray を MEX 関数に 1 番目の引数 (prhs[0]) として渡す場合、複素数データへのポインターを取得するには、以下の呼び出しを使用します。

mxGPUArray const * A = mxGPUCreateFromMxArray(prhs[0]);
mwSize numel_complex = mxGPUGetNumberOfElements(A);
double2 * d_A = (double2 const *)(mxGPUGetDataReadOnly(A));

この配列を 2 倍の長さの実数倍精度配列として扱うには、以下を実行します。

mxGPUArray const * A = mxGPUCreateFromMxArray(prhs[0]);
mwSize numel_real =2*mxGPUGetNumberOfElements(A);
double * d_A = (double const *)(mxGPUGetDataReadOnly(A));

GPU においてデータを複素数形式と実数形式の間で変換する関数にはさまざまなものがあります。それらの操作では、データをインターリーブするためにコピーを作成する必要があります。関数 mxGPUCreateComplexGPUArray は 2 つの実数値 mxGPUArray を入力として取り、その要素をインターリーブして、同じ長さをもつ単一の複素数 mxGPUArray を出力します。関数 mxGPUCopyReal および mxGPUCopyImag はそれぞれ、実数部の要素と虚数部の要素を実数型の新しい mxGPUArray にコピーします(mxGPUArray オブジェクトには、関数 mxGetImagData に相当する関数はありません)。

GPU MEX ファイルのコンパイル

MATLAB の mexcuda コマンドを使用して、CUDA コードを含む MEX ファイルをコンパイルします。次のコマンドを使用して例のファイルをコンパイルできます。

mexcuda mexGPUExample.cu

CUDA ツールキットが検出されないか、サポートされているバージョンでない場合、MATLAB は MATLAB と共にインストールされる NVIDIA nvcc コンパイラを使用して CUDA コードをコンパイルします。mexcuda が使用しているコンパイラを確認するには、mexcuda コマンドで詳細出力を得るための -v フラグを使用します。

MATLAB と共にインストールされる CUDA ツールキットには、CUDA ツールキットで使用可能なすべてのライブラリが含まれているわけではありません。MATLAB と共にインストールされていない特定のライブラリにリンクするには、CUDA ツールキットをインストールします。gpuDevice を使用して、MATLAB に必要な CUDA ツールキットのバージョンをチェックできます。CUDA ツールキットの詳細については、CUDA ツールキットを参照してください。

mexcuda で、インストール済みの CUDA ツールキット内に NVIDIA コンパイラ (nvcc) が見つからない場合は、既定以外の場所にインストールされている可能性があります。システム上の nvcc の場所を環境変数 MW_NVCC_PATH に保存して指定することができます。この変数を設定するには、MATLAB コマンド setenv を使用します。以下に例を示します。

setenv('MW_NVCC_PATH','/usr/local/CUDA/bin')

mexcuda では Visual Studio® コンパイラのサブセットのみがサポートされています。詳細については、NVIDIA ツールキットのドキュメンテーションを参照してください。

参考

| |

関連するトピック