我尝试为内核创建2个本地数组。我的目标是将全局输入缓冲区复制到第一个数组(arr1),并实例化第二个数组(arr2),以便可以在以后访问和设置其元素。
我的内核看起来像这样:
__kernel void do_things (__global uchar* in, __global uchar* out,
uint numIterations, __local uchar* arr1, __local uchar* arr2)
{
size_t work_size = get_global_size(0) * get_global_size(1);
event_t event;
async_work_group_copy(arr1, in, work_size, event);
wait_group_events(1, &event);
int cIndex = (get_global_id(0) * get_global_size(1)) + get_global_id(1);
arr2[cIndex] = 0;
//Do other stuff later
}
在我调用它的C ++代码中,我设置了这样的内核参数:
//Create input and output buffers
cl_mem inputBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY |
CL_MEM_COPY_HOST_PTR, myInputVector.size(), (void*)
myInputVector.data(), NULL);
cl_mem outputBuffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY,
myInputVector.size(), NULL, NULL);
//Set kernel arguments.
clSetKernelArg(kernel, 0, sizeof(cl_mem), (void*)&inputBuffer));
clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&outputBuffer));
clSetKernelArg(kernel, 2, sizeof(cl_uint), &iterations));
clSetKernelArg(kernel, 3, sizeof(inputBuffer), NULL));
clSetKernelArg(kernel, 4, sizeof(inputBuffer), NULL));
myInputVector是一个充满uchars的向量。
然后,我用2D工作大小排队,行* cols大。 myInputVector的大小为rows * cols。
//Execute the kernel
size_t global_work_size[2] = { rows, cols }; //2d work size
status = clEnqueueNDRangeKernel(commandQueue, kernel, 2, NULL,
global_work_size, NULL, 0, NULL, NULL);
问题是,我在运行内核时遇到了崩溃问题。具体来说,内核中的这一行:
arr2[cIndex] = 0;
负责崩溃(省略它会使它不再崩溃)。错误如下:
*** glibc detected *** ./MyProgram: free(): invalid pointer: 0x0000000001a28fb0 ***
我想要的就是能够与arr1一起访问arr2。 arr2应与arr1的大小相同。如果是这样,为什么我会收到这个奇怪的错误?为什么这是一个无效的指针?
答案 0 :(得分:0)
问题是您只为本地缓冲区分配sizeof(cl_mem)
。而cl_mem
只是某种指针类型的typedef(因此取决于你的系统,4到8个字节)。
在你的内核中发生的事情是,你访问的内容超出了你分配的本地缓冲区的大小,GPU会启动内存故障。
clSetKernelArg(kernel, 3, myInputVector.size(), NULL);
clSetKernelArg(kernel, 4, myInputVector.size(), NULL);
应该解决你的问题。另请注意,您提供的大小是以字节为单位的大小,因此您需要乘以向量元素类型的sizeof
(代码中不清楚)。