以下のOpenCLカーネルを、1000000 x100の2次元グローバルワークサイズと1x100のローカルワークサイズで実行しています。
__kernel void myKernel(
const int length,
const int height,
and a bunch of other parameters) {
//declare some local arrays to be shared by all 100 work item in this group
__local float LP [length];
__local float LT [height];
__local int bitErrors = 0;
__local bool failed = false;
//here come my actual computations which utilize the space in LP and LT
}
ただし、パラメータlength
およびheight
はコンパイル時に不明であるため、これはコンパイルを拒否します。しかし、これを正しく行う方法は私にはまったくわかりません。 memallocでポインターを使用する必要がありますか?メモリがワークグループ全体に1回だけ割り当てられ、ワークアイテムごとに1回割り当てられないように、これを処理するにはどうすればよいですか?
必要なのは、ワークグループ全体で共有される2つのfloat配列、1つのintと1つのブール値です(つまり、100個の作業項目すべて)。しかし、私はこれを正しく行う方法を見つけることができません...
比較的簡単です。ローカル配列を引数としてカーネルに渡すことができます。
kernel void myKernel(const int length, const int height, local float* LP,
local float* LT, a bunch of other parameters)
次に、value
のNULL
と引数に割り当てるサイズ(バイト単位)に等しいsize
を使用してkernelargumentを設定します。したがって、次のようになります。
clSetKernelArg(kernel, 2, length * sizeof(cl_float), NULL);
clSetKernelArg(kernel, 2, height* sizeof(cl_float), NULL);
ローカルメモリは(プライベートではなく)常にワークグループによって共有されるため、bool
とint
は問題ないと思いますが、そうでない場合は、いつでも引数として渡すことができます。
あなたの問題とは実際には関係ありませんが(これを実行する予定のハードウェアがわからないため、必ずしも関係ありません)、少なくともgpusは、特定の2の累乗の倍数ではない作業サイズを特に好みません(I nvidiaの場合は32、AMDの場合は64だったと思います)。つまり、おそらく128項目のワークグループが作成され、そのうち最後の28項目は基本的に無駄になります。したがって、gpuでopenclを実行している場合、サイズ128のワークグループを直接使用すると(グローバルワークサイズを適切に変更すると)、パフォーマンスが向上する可能性があります。
補足として:なぜ誰もがkernel, local and global
にアンダースコアのバリアントを使用するのか理解できませんでしたが、私にははるかに醜いようです。
特に配列ではなく単純な変数である場合は、カーネルの外部にすべてのローカルメモリを割り当てる必要はありません。
コードをコンパイルできない理由は、OpenCLがローカルメモリの初期化をサポートしていないためです。これはドキュメントで指定されています( https://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/local.html )。 CUDAでも実行できません( 共有メモリ配列のデフォルト値を設定する方法はありますか? )
ps:Grizzlyからの回答で十分であり、コメントとして投稿できればよいのですが、評判ポリシーによって制限されています。ごめんなさい。
次のように配列を宣言することもできます。
__local float LP[LENGTH];
そして、LENGTHをカーネルコンパイルの定義として渡します。
int lp_size = 128; // this is an example; could be dynamically calculated
char compileArgs[64];
sprintf(compileArgs, "-DLENGTH=%d", lp_size);
clBuildProgram(program, 0, NULL, compileArgs, NULL, NULL);