OpenCL内核执行后数组结果异常,请求原因排查
问题分析与解决方案
嘿,我一眼就抓到了导致你代码出问题的核心原因,咱们来一步步拆解:
最关键的错误:内核参数索引搞反了
你看init()函数里设置内核参数的这段代码:
ret = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void*)&a_mem_obj);
你的OpenCL内核只有一个参数__global int* c,但OpenCL的内核参数索引是从0开始计数的!你这里用了索引1,相当于让内核去读一个根本没设置的第二个参数,内核拿到的是一块随机的垃圾内存地址,对这块内存做自增操作后写回,自然就会出现莫名其妙的负数和乱码。
次要小问题:工作项分组不匹配
你设置的全局工作项数量是SIZE=100,本地工作项是64,100并不是64的整数倍。虽然多数OpenCL实现会自动补全到下一个64的倍数(也就是128),但最好还是让全局工作项数是本地工作项的整数倍,比如把global_item_size改成128,或者把local_item_size改成25/50这类能整除100的数,避免潜在的边界异常。
修正后的关键代码
首先修正内核参数索引
// Set the arguments of the kernel ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void*)&a_mem_obj); // 把1改成0就对了 if (ret != CL_SUCCESS) std::cout << ret << 13;
可选:调整工作项大小(避免分组不匹配)
要么把全局工作项改成64的倍数:
size_t static global_item_size = 128; size_t static local_item_size = 64;
要么直接让Runtime自动分配本地工作项:
ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, NULL, 0, NULL, NULL);
修正后的运行结果
改完之后再运行,所有元素都会从1变成2,不会再出现那些奇怪的负数啦!
内容的提问来源于stack exchange,提问作者Berecz Balázs
相关产品推荐
相关产品推荐

