我有一个像这样的简单内核:
__kernel void cycle(__global int * grid, int idx) {
grid[idx] = idx;
}
我在循环中运行clEnqueueTask()
,如下所示:
for (int i = 0; i < size; i++) {
int arg = i;
clSetKernelArg(kernel_id, 1, &arg);
clEnqueueTask(command_queue, kernel_id, 0, NULL, NULL);
}
预期结果是[0 ...size - 1]
的数组,但它只将最后一个索引设置为适当的值。其他的保持默认(在我的情况下为0)。
我尝试在数组的第一个单元格(idx
)中累积grid[0] += idx
参数的值,它给出了从1
到{{1}的预期整数和因此,参数被正确传递并且任务正确执行。
感谢任何帮助!
答案 0 :(得分:1)
可能对您的问题原因提出建议:
arg
整数在完整循环期间具有相同的内存地址;当它传递给CL内核时,你传递地址(而不是值的副本),因此每次所有实例的值都会改变。
但是,这表明所有网格数组值都等于相同的最后一个值,除了最后一个之外,不是零。
为什么计算总和时这会起作用?
我的猜测是你不会在grid
数组中存储单个值(需要在内核完成并读回数据后保留);相反,该值会被添加并分配到grid[0]
,grid[0]
中的值不再依赖idx
。
不可否认,这有些模糊,涉及一些猜测,但这里有一些你可以试试的东西:
for (int i = 0; i < size; i++) {
int *arg = malloc(sizeof(*arg));
*arg = i;
clSetKernelArg(kernel_id, 1, arg, sizeof(*arg));
clEnqueueTask(command_queue, kernel_id, 0, NULL, NULL);
}
(由于某种原因,您的示例没有size
的{{1}}参数;不确定原因。)
显然,通常你会将clSetKernelArg
分配为一个大小为arg
的数组,而不是每次迭代都要对其进行mallocing,但是让我们保持这个例子的设计。
如果这样可行,你可以到处看看你可以size
free
到什么时候,因为上面的内存泄漏很多。我怀疑你可以在循环中释放arg
。