私はベクトル操作を行い、ベクトル加算と乗算を使って小さなダミープログラムを試していました。しかし、共有メモリに関する知識が限られているため、コードは実行されません。インターネット上のすべての情報源は、私のベクトル問題に変換できない2Dマトリックス操作を示しています。私がOpenCLで初心者であるという事実を考慮して、どこが間違っているのかを説明してください。コードは以下の通りである:OpenCLの共有メモリ
ホスト・コード:
std::vector<cl::Platform> platforms;
std::vector<cl::Device> devices;
cl::Context context;
cl::CommandQueue queue;
cl::Program program;
cl::Kernel kernel;
cl::Platform::get(&platforms);
deviceUsed = 0;
cl_context_properties properties[] =
{ CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[0])(),0 };
context = cl::Context(CL_DEVICE_TYPE_ALL, properties);
devices = context.getInfo<CL_CONTEXT_DEVICES>();
queue = cl::CommandQueue(context, devices[deviceUsed]);
cl::Program::Sources source(1, std::make_pair(kernel_source.c_str(), kernel_source.size()));
program = cl::Program(context, source);
program.build(devices);
std::vector <float> a;
std::vector <float> b;
std::vector <float> sum;
std::vector <float> prod;
int globalSize = 128;
int localSize = 16;
a.resize(globalSize);
b.resize(globalSize);
sum.resize(globalSize);
prod.resize(globalSize);
for (int i = 0; i < globalSize ; i++)
{
a[i] = 1.0f * i;
b[i] = 5.0f * i;
}
cl::Buffer buffer_A;
cl::Buffer buffer_B;
cl::Buffer buffer_sum;
cl::Buffer buffer_prod;
buffer_A = cl::Buffer (context, CL_MEM_READ_WRITE, sizeof(float) * globalSize);
buffer_B = cl::Buffer (context, CL_MEM_READ_WRITE, sizeof(float) * globalSize);
queue.enqueueWriteBuffer(buffer_A, CL_TRUE, 0, sizeof(float) * globalSize , &a[0]);
queue.enqueueWriteBuffer(buffer_B, CL_TRUE, 0, sizeof(float) * globalSize , &b[0]);
buffer_sum = cl::Buffer(context, CL_MEM_WRITE_ONLY, sizeof(float) * globalSize);
buffer_prod = cl::Buffer(context, CL_MEM_WRITE_ONLY, sizeof(float) * globalSize);
kernel.setArg(0, buffer_A);
kernel.setArg(1, buffer_B);
kernel.setArg(2, buffer_sum);
kernel.setArg(3, buffer_prod);
queue.enqueueNDRangeKernel(kernel, cl::NullRange, cl::NDRange(globalSize/localSize), cl::NDRange(N), NULL);
queue.finish();
queue.enqueueReadBuffer(buffer_sum, CL_TRUE, 0, sizeof(float) * globalSize, &sum[0]);
queue.enqueueReadBuffer(buffer_prod, CL_TRUE, 0, sizeof(float) * globalSize, &prod[0]);
カーネル:私はあなたのカーネルがコンパイルされませんので、あなたのコードが実行されないと思われる
#define STRINGI(ker) #ker
std::string kernel_source = STRINGI(
__kernel void KernelAddMul(__global float* a, __global float* b, __global float* sum, __global float* prod)
{
unsigned int j = get_local_id(0);
int N = get_local_size(0);
unsigned int i = N * get_global_id(0) + j;
float locSum[N];
float locProd[N];
__local float Asub[N];
__local float Bsub[N];
for(int k = 0; k < N; k++){
Asub[k] = a[i];
Bsub[k] = b[i];
barrier(CLK_LOCAL_MEM_FENCE);
locSum[k] = Asub[k] + Bsub[k];
locProd[k] = Asub[k] * Bsub[k];
barrier(CLK_LOCAL_MEM_FENCE);
sum[i] = locSum[k];
prod[i] = locProd[k];
}
}
);
共有メモリは、1つのワークグループ内でしか見られない、より高速なメモリです。カーネル間では、clバッファを使用してグローバルメモリを介してデータにアクセスするため、共有メモリはカーネル内でのみ「割り当て」および使用することができます。 1Dの場合は、おそらく共有メモリを使用して削減し、中間値を保存してグローバルメモリに書き直さないようにします。それにアクセスするには '__local__'を使います。 – theoden
コードが実行されないとはどういう意味ですか?それは実行され、間違った結果を与えるか、それとも失敗するか?それぞれのOpenCL呼び出しをチェックして、CL_SUCCESSを戻すかどうかを確認する必要があります。より多くの情報を提供できるのであれば、私たちには有益です。 –
@parallelhighway Intel SDKを使用していて、コードがコンパイルされています。しかし、私がsumとprodの値をカーネルから返すと、すべての0が表示されます。私は何かが些細なことを逃していると思う。ローカルコードとグローバルメモリが通信するホストコードまたはカーネルコードのenqueueNDRangeKernelステートメントの引数に問題がある可能性があります。コードを一度見てください。ありがとう:) – Ijjz