clSetKernelArg arg_value不是内存对象

时间:2012-02-27 07:16:28

标签: opencl

在OpenCL中,我可以将内核参数设置如下吗?

cl_uint a = 0;
kernel.setArg(0, sizeof(a), &a);

我想从内核函数读取和写入一个值,而不仅仅是写入。

3 个答案:

答案 0 :(得分:4)

以这种方式设置内核参数只能用于内核的输入。您要读取的任何输出(在后续内核或主机程序中)都必须写入缓冲区或映像。在您的情况下,这意味着您需要创建单元素缓冲区并将缓冲区传递给内核。

考虑这一点的一种方法是,当您使用参数& a调用setArg时,OpenCL内核使用a的,而不是 location 一个。如果内核要写入内核参数零,那么你的宿主程序就无法恢复写入的值。

答案 1 :(得分:2)

您的代码会创建类型为unsigned int的参数,而不是指向unsigned int的指针。 clSetKernelArg使用指向参数值的指针,而不是值本身。 如果要传递指针参数,则必须使用clCreateBuffer创建一个缓冲区(即使它只是一个值),并使用生成的clSetKernelArg调用cl_mem

以下代码在 __ global 内存中为1 cl_uint创建一个缓冲区,并将my_value的值复制到该内存中。运行内核后,它会将(可能已修改的)值复制回my_value

cl_uint my_value = 0;
const unsigned int count = 1;
// Allocate buffer
cl_mem hDeviceMem = clCreateBuffer(hContext, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, count * sizeof(cl_uint), &my_value, &nError);
// Set pointer to buffer as argument
clSetKernelArg(hKernel, 0, sizeof(cl_mem), &hDeviceMem);
// Run kernel
clEnqueueNDRangeKernel(...);
// Copy values back
clEnqueueReadBuffer(hCmdQueue, hDeviceMem, CL_TRUE, 0, count * sizeof(cl_uint), &my_value, 0, NULL, NULL);

你的内核应该是这样的:

__kernel void myKernel(__global unsigned int* value)
{
    // read/write to *value here
}

答案 2 :(得分:0)

这应该与将1长度向量作为参数发送相同。您可能必须在内核定义中使用__global uint aParam。