Main Content

生成された関数インターフェイスにおける動的割り当ての C++ 配列の使用

ほとんどの場合、配列を受け取るか配列を返す MATLAB® 関数のコードを生成すると、生成された CUDA® 関数のインターフェイスでも配列が使用されます。コンパイル時に配列サイズが不明な場合や、配列の境界が事前定義されたしきい値を超える場合、生成される配列のメモリは動的に割り当てられます。

既定では、動的に割り当てられる配列は、生成コードで C スタイルの emxArray データ構造を使用して実装されます。または、動的に割り当てられる配列を、生成コードで coder::gpu_array と呼ばれるクラス テンプレートとして実装できます。coder::gpu_array には、emxArray スタイルのデータ構造と比べて次のようないくつかの利点があります。

  • 生成コードが例外安全になる。

  • 生成コードが読みやすくなる。

  • 入力データの初期化と出力データの操作が容易になり、C++ との統合が向上する。

  • coder::gpu_array は MATLAB 付属のヘッダー ファイルで定義されているため、生成コードよりも前にインターフェイスのコードを記述できる。

生成された CUDA C++ 関数と統合するカスタム CUDA コードで動的割り当ての配列を使用するにあたっては、coder::gpu_array テンプレートの使用方法を学習してください。

インターフェイス世代の変更

既定では、生成される CUDA コードは C スタイルの emxArray データ構造を使用して、動的に割り当てられる配列を実装します。代わりに、動的に割り当てられる配列を実装するために、coder::gpu_array テンプレートを使用する CUDA コードを生成することもできます。coder::gpu_array テンプレートを生成するには、次のいずれかを実行します。

  • コード構成オブジェクト (coder.MexCodeConfigcoder.CodeConfig、または coder.EmbeddedCodeConfig) で、DynamicMemoryAllocationInterface パラメーターを 'C++' に設定。

  • GPU Coder™ アプリの [メモリ] タブで、[動的メモリ割り当てインターフェイス][C++ の coder::array を使用] に設定。

coder::gpu_array クラス テンプレートの使用

MATLAB 関数の CUDA コードを生成すると、コード ジェネレーターによって、ビルド フォルダーにヘッダー ファイル coder_gpu_array.hcoder::array.h が生成されます。coder_gpu_array.h ヘッダー ファイルには、名前空間 coder のクラス テンプレート gpu_array の定義および関数テンプレート arrayCopyCpuToGpuarrayCopyGpuToCpu の定義が含まれています。coder::gpu_array テンプレートは、動的に割り当てられる配列を生成コードに実装します。このテンプレート用の宣言は次のとおりです。

template <typename T, int32_T N> class gpu_array
配列には T 型の要素が格納され、N 個の次元をもちます。たとえば、カスタム CUDA コードで int32_T 型の要素を含む 2 次元動的配列 myArray を宣言するには、次を使用します。

coder::gpu_array<int32_T, 2> myArray

関数テンプレート arrayCopyCpuToGpu および arrayCopyGpuToCpu は、CPU のメモリと GPU のメモリの間のデータ転送を実装します。CPU では、動的に割り当てられる配列が coder::array テンプレートを使用して実装されます。カスタム コードで動的配列を作成して操作するために使用する API の詳細については、生成された関数インターフェイスでの動的に割り当てられた C++ 配列の使用を参照してください。

生成コード (カスタム main 関数など) と統合するカスタム CUDA コードで動的割り当ての配列を使用するには、カスタム .cu ファイルに coder_gpu_array.hcoder_array.h のヘッダー ファイルを含めます。

可変サイズの数値配列を受け入れて返す C++ コードの生成

この例では、生成されたサンプル main 関数をカスタマイズして、プロジェクトで coder::gpu_arraycoder::array のクラス テンプレートを使用する方法を示します。

目標は、int32_T の要素の配列を受け入れて返すことができる xTest1 用の CUDA 実行可能ファイルを生成することです。配列の最初の次元を大きさ 1 にし、2 番目の次元を無制限にします。

  1. 配列 X を受け入れ、スカラー A をその各要素に追加し、結果の配列 Y を返す MATLAB 関数 xTest1 を定義します。

    function Y = xTest1(X, A)
    Y = X;
    for i = 1:numel(X)
        Y(i) = X(i) + A;
    end
    
  2. xTest1 の初期ソース コードを生成し、xTest1.h をコード生成フォルダーから現在のフォルダーに移動します。以下のコマンドを使用します。

    cfg = coder.gpuConfig('lib');
    cfg.DynamicMemoryAllocationInterface = 'C++';
    cfg.GenerateReport = true;
    inputs = {coder.typeof(int32(0), [1 inf]), int32(0)};
    
    codegen -config cfg -args inputs xTest1.m
    

    生成コード内の xTest1 の関数プロトタイプは次のようになります。

    extern void xTest1(const coder::array<int, 2U> &X, int A,
                       coder::array<int, 2U> &Y);
    

    上記の関数プロトタイプと互換性のある入力配列と出力配列を提供することにより、この生成コードと接続します。

  3. 現在の作業フォルダーにあるファイル xTest1_main.cu で CUDA main 関数を定義します。

    この main 関数には、それぞれ coder::gpu_arraycoder::array のクラス テンプレート定義を含むヘッダー ファイル coder_gpu_array.hcoder_array.h が含まれます。main 関数は次のアクションを実行します。

    • myArraymyResultint32_T の要素の 2 次元 coder::array 動的配列として宣言。

    • set_size メソッドを使用して、myArray の 2 つの次元のサイズを 1100 に動的に設定。

    • myResult.size を使用して、myResult のサイズ ベクトルにアクセス。

    #include<iostream>
    #include<coder_array.h>
    #include<xTest1.h>
    
    int main(int argc, char *argv[])
    {
        static_cast<void>(argc);
        static_cast<void>(argv);
        
        // Instantiate the input variable by using coder::array template
        coder::array<int32_T, 2> myArray;     
        
        // Allocate initial memory for the array
        myArray.set_size(1, 100);             
    
        // Access array with standard C++ indexing
        for (int i = 0; i < myArray.size(1); i++) {
            myArray[i] = i;                   
        }
        
        // Instantiate the result variable by using coder::array template
        coder::array<int32_T, 2> myResult;
    
        // Pass the input and result arrays to the generated function
        xTest1(myArray, 1000, myResult);
    
        for (int i = 0; i < myResult.size(1); i++) {
            if (i > 0) std::cout << " ";
            std::cout << myResult[i];
            if (((i+1) % 10) == 0) std::cout << std::endl;
        }
        std::cout << std::endl;
    
        return 0;
    }
  4. 次のスクリプトを実行してコードを生成します。

    cfg = coder.gpuConfig('exe');
    cfg.DynamicMemoryAllocationInterface = 'C++';
    cfg.GenerateReport = true;
    cfg.CustomSource = 'xTest1_main.cu';
    cfg.CustomInclude = '.';
    codegen -config cfg -args inputs xTest1_main.cu xTest1.m
    
  5. コード ジェネレーターは、現在の作業フォルダーに実行可能ファイル xTest1 を生成します。以下のコマンドを使用して実行可能ファイルを実行します。

    if ispc
      !xtest1.exe
    else
      !./xTest1
    end
     1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
     1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
     1020 1021 1022 1023 1024 1025 1026 1027 1028 1029
     1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
     1040 1041 1042 1043 1044 1045 1046 1047 1048 1049
     1050 1051 1052 1053 1054 1055 1056 1057 1058 1059
     1060 1061 1062 1063 1064 1065 1066 1067 1068 1069
     1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
     1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
     1090 1091 1092 1093 1094 1095 1096 1097 1098 1099
    

制限

  • coder::gpu_array を使用する CUDA コードを生成するには、GPU メモリ割り当てモードを discrete に設定しなければなりません。

    GPU Coder アプリでメモリ割り当てモードを変更するには、[詳細設定]、[GPU Coder] の下にある [Malloc モード] ドロップダウン ボックスを使用します。コマンド ライン インターフェイスを使用する場合、MallocMode ビルド構成プロパティを使用し、それを 'discrete' または 'unified' に設定します。

  • GPU Coder は Simulink®coder::gpu_array をサポートしません。

参考

|

関連するトピック