生成された関数インターフェイスにおける動的割り当ての 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.MexCodeConfig
、coder.CodeConfig
、またはcoder.EmbeddedCodeConfig
) で、DynamicMemoryAllocationInterface
パラメーターを'C++'
に設定。GPU Coder™ アプリの [メモリ] タブで、[動的メモリ割り当てインターフェイス] を
[C++ の coder::array を使用]
に設定。
coder::gpu_array
クラス テンプレートの使用
MATLAB 関数の CUDA コードを生成すると、コード ジェネレーターによって、ビルド フォルダーにヘッダー ファイル coder_gpu_array.h
と coder::array.h
が生成されます。coder_gpu_array.h
ヘッダー ファイルには、名前空間 coder
のクラス テンプレート gpu_array
の定義および関数テンプレート arrayCopyCpuToGpu
と arrayCopyGpuToCpu
の定義が含まれています。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.h
と coder_array.h
のヘッダー ファイルを含めます。
可変サイズの数値配列を受け入れて返す C++ コードの生成
この例では、生成されたサンプル main 関数をカスタマイズして、プロジェクトで coder::gpu_array
と coder::array
のクラス テンプレートを使用する方法を示します。
目標は、int32_T
の要素の配列を受け入れて返すことができる xTest1
用の CUDA 実行可能ファイルを生成することです。配列の最初の次元を大きさ 1 にし、2 番目の次元を無制限にします。
配列
X
を受け入れ、スカラーA
をその各要素に追加し、結果の配列Y
を返す MATLAB 関数xTest1
を定義します。function Y = xTest1(X, A) Y = X; for i = 1:numel(X) Y(i) = X(i) + A; end
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);
上記の関数プロトタイプと互換性のある入力配列と出力配列を提供することにより、この生成コードと接続します。
現在の作業フォルダーにあるファイル
xTest1_main.cu
で CUDA main 関数を定義します。この main 関数には、それぞれ
coder::gpu_array
とcoder::array
のクラス テンプレート定義を含むヘッダー ファイルcoder_gpu_array.h
とcoder_array.h
が含まれます。main 関数は次のアクションを実行します。myArray
とmyResult
をint32_T
の要素の 2 次元coder::array
動的配列として宣言。set_size
メソッドを使用して、myArray
の 2 つの次元のサイズを1
と100
に動的に設定。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; }
次のスクリプトを実行してコードを生成します。
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
コード ジェネレーターは、現在の作業フォルダーに実行可能ファイル
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
をサポートしません。