ドキュメンテーション センター

  • 評価版
  • 製品アップデート

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

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

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

    メモ:    gpuArray データ用の MEX 関数の作成は、64 ビットのプラットフォーム (win64、glnxa64、maci64) のみでサポートされます。

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

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

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

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

matlabroot/toolbox/distcomp/gpu/extern/src/mex/mexGPUExample.cumatlabroot/toolbox/distcomp/gpu/extern/src/mex/mexGPUExample.cu

このファイルには、以下の 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 ファイルのコンパイルの設定

  • CUDA コードを含む MEX ソース ファイルに付ける名前の拡張子は、.c.cpp でなく、.cu でなければなりません。

  • MEX ファイルをコンパイルする前に、プラットフォーム用に用意されている mexopts ファイルを MEX ソース ファイルと同じフォルダーにコピーします。このファイルは以下の場所にあります。

    matlabroot/toolbox/distcomp/gpu/extern/src/mex/glnxa64/mexopts.sh  (Linux)
    matlabroot/toolbox/distcomp/gpu/extern/src/mex/maci64/mexopts.sh  (Macintosh)
    matlabroot\toolbox\distcomp\gpu\extern\src\mex\win64\mexopts.bat (Windows)
  • 使用する NVIDIA コンパイラ (nvcc) のバージョンは、GPUDevice オブジェクトの ToolkitVersion プロパティと一致していなければなりません。

  • コンパイルの前に、nvcc フォルダーの場所が検索パス上にあるか、または nvcc の場所へのパスが環境変数 MW_NVCC_PATH に設定されていることを確認します。この変数を設定するには、MATLAB setenv コマンドを使用します。以下に例を示します。

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

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

オプション ファイルを設定したら、MATLAB の mex コマンドを使用して、CUDA コードを含む MEX ファイルをコンパイルします。次のコマンドを使用して例のファイルをコンパイルできます。

mex mexGPUExample.cu

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

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

x = gpuArray.ones(4,4);
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 との統合に使用できます。MEX ファイルによる手法と CUDAKernel による手法のどちらを選択するかを決定するに当たっては、以下を考慮してください。

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

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

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

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

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

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

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 に相当する関数はありません)。

ホスト側ライブラリの呼び出し

付属の MEX ファイル例のコードには、GPU 用に独自コードを作成する方法が示されています。たとえば、NPP ライブラリを呼び出すには、MEX ファイルに次の行を書き込みます。

#include "npp.h"

続けて、プラットフォームに応じて以下の変更を行います。

  • Linux では、値 $TMW_ROOT/bin/$Arch/libnpp.so.5.0 を含むよう、matlabroot/toolbox/distcomp/gpu/extern/src/mex/glnxa64/mexopts.sh で変数 CXXLIBS の設定を変更します。

  • Macintosh では、フラグ -lnpp を含むよう、matlabroot/toolbox/distcomp/gpu/extern/src/mex/maci64/mexopts.sh で変数 CXXLIBS の設定を変更します。

  • Windows では、npp.lib を含むよう、mexopts.bat で変数 LINKFLAGS の値を変更します。

この情報は役に立ちましたか?