私の前の質問に基づいて:
私はまだ画像をコピーしようとしています(実用的な理由はありません。簡単なものから始めます):
画像には200 * 300 == 60000ピクセルが含まれています。
によると、作業項目の最大数は4100CL_DEVICE_MAX_WORK_GROUP_SIZE
です。
kernel1:
std::string kernelCode =
"void kernel copy(global const int* image, global int* result)"
"{"
"result[get_local_id(0) + get_group_id(0) * get_local_size(0)] = image[get_local_id(0) + get_group_id(0) * get_local_size(0)];"
"}";
キュー:
for (int offset = 0; offset < 30; ++offset)
queue.enqueueNDRangeKernel(imgProcess, cl::NDRange(offset * 2000), cl::NDRange(60000));
queue.finish();
セグメンテーション違反を起こします、何が問題なのですか?
最後のパラメータcl::NDRange(20000)
ではそうではありませんが、画像の一部のみを返します。
また、なぜこのカーネルを使用できないのかわかりません。
kernel2:
std::string kernelCode =
"void kernel copy(global const int* image, global int* result)"
"{"
"result[get_global_id(0)] = image[get_global_id(0)];"
"}";
31番目のスライドでこのプレゼンテーションを見てください。
単にglobal_idを使用できないのはなぜですか?
EDIT1
Platfrom:AMDアクセラレーテッド並列処理
デバイス:AMD Athlon(tm)IIP320デュアルコアプロセッサ
EDIT2
huseyin tugrul Buyukisikの回答に基づく結果:
EDIT3
最後のパラメータでcl::NDRange(20000)
:
カーネルは両方の方法で最初のものです。
EDIT4
std::string kernelCode =
"void kernel copy(global const int* image, global int* result)"
"{"
"result[get_global_id(0)] = image[get_global_id(0)];"
"}";
//...
cl_int err;
err = queue.enqueueNDRangeKernel(imgProcess, cl::NDRange(0), cl::NDRange(59904), cl::NDRange(128));
if (err == 0)
qDebug() << "success";
else
{
qDebug() << err;
exit(1);
}
成功を印刷します。
多分これは間違っていますか?
int size = _originalImage.width() * _originalImage.height();
int* result = new int[size];
//...
cl::Buffer resultBuffer(context, CL_MEM_READ_WRITE, size);
//...
queue.enqueueReadBuffer(resultBuffer, CL_TRUE, 0, size, result);
有罪は:
cl::Buffer imageBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(int) * size, _originalImage.bits());
cl::Buffer resultBuffer(context, CL_MEM_READ_ONLY, sizeof(int) * size);
queue.enqueueReadBuffer(resultBuffer, CL_TRUE, 0, sizeof(int) * size, result);
のsize
代わりに使用しましたsizeof(int) * size
。
編集2:
非定数メモリ指定子を試してください(おそらくCPUと互換性がありません):
std::string kernelCode =
"__kernel void copy(__global int* image, __global int* result)"
"{"
"result[get_global_id(0)] = image[get_global_id(0)];"
"}";
また、バッファオプションも変更する必要があるかもしれません。
編集:
'global'および 'kernel'指定子の前に3つの'__'を忘れたので、試してみてください。
std::string kernelCode =
"__kernel void copy(__global const int* image, __global int* result)"
"{"
"result[get_global_id(0)] = image[get_global_id(0)];"
"}";
合計要素は60000ですが、非特権領域をオーバーフローして読み取り/書き込みするオフセット+60000を実行しています。
opencl 1.2 c ++バインディングのndrangeの通常の使用法は次のとおりです。
cl_int err;
err=cq.enqueueNDRangeKernel(kernelFunction,referenceRange,globalRange,localRange);
次に、探している実際のエラーコードのエラーを確認します。0は成功を意味します。**
作業をより小さな部分に分割したい場合は、各ユニットの範囲を60000 / Nで制限する必要があります
30の部分で割ると、
for (int offset = 0; offset < 30; ++offset)
queue.enqueueNDRangeKernel(imgProcess, cl::NDRange(offset * 2000), cl::NDRange(60000/30));
queue.finish();
そして、各バッファのサイズを再確認します。例:sizeof(cl_int)* arrElementNumber
整数のサイズはデバイス整数と同じではない可能性があるためです。60000個の要素が必要ですか?次に、バッファを作成するときにサイズとして渡すために240000バイトが必要です。
互換性のために、このコードを別のマシンで実行する場合は、バッファを作成する前に整数のサイズを確認する必要があります。
あなたはすでにこれを知っているかもしれませんが、とにかく私は言うつもりです:
CL_DEVICE_MAX_WORK_GROUP_SIZE
計算ユニットでローカル/共有メモリを共有できるスレッドの数です。このためだけに作業を分割する必要はありません。Openclはこれを自動的に実行し、作業全体に沿ってスレッドごとに一意のグローバルIDを提供し、計算ユニット内のスレッドごとに一意のローカルIDを提供します。CL_DEVICE_MAX_WORK_GROUP_SIZEが4100の場合、計算ユニットで同じ変数を共有するスレッドを作成できます。1回のスイープで60000個の変数すべてを追加するだけで計算できます。このために複数のワークグループが作成され、各グループにはグループIDがあります。
// this should work without a problem
queue.enqueueNDRangeKernel(imgProcess, cl::NDRange(0), cl::NDRange(60000));
AMD gpuまたはcpuを使用していて、msvcを使用している場合は、amdサイトからcodexlをインストールし、ドロップダウンメニューからシステム情報を選択して関連する番号を確認できます。
あなたのデバイスはどれですか?ワークグループの最大サイズが4100のデバイスは見つかりませんでした。私のCPUは1024、GPUは256です。それはxeon-phiですか?
たとえば、ここでは、合計作業項目が作業グループサイズの256 * 256倍になる場合があります。
Codexlには、パフォーマンスプロファイリング、最大のパフォーマンスが必要な場合のコードのトレース、バグ修正など、その他の優れた機能があります。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加