在数组索引处写入仅适用于队列

时间:2016-11-19 21:35:09

标签: opencl

我有一个像这样的简单内核:

__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}的预期整数和因此,参数被正确传递并且任务正确执行。

感谢任何帮助!

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