3

我正在开发一个 OpenCL 程序,但每次执行的输出都不同。我认为这与将参数传递给内核有关,因为当我对特定执行的值进行硬编码时,每次执行后的输出都是相似的。

我的内核看起来像这样:

__kernel void sample_kernel(__global double *BufferA, int scalar1, int scalar2, int scalar3, ...) {

    for(int i = -1*scalar1; i < scalar1; i++) {
        for(int j = -1*scalar1; j < scalar1, j++) {
            if(scalar2 > 0 && scalar3 > 0) // do something.
        }
    }
}

这就是我设置内核参数的方式:

int scalar1 = 1;
int scalar2 = 2;
int scalar3 = 3;

Samplekernel.setArg(0, d_BufferA);
Samplekernel.setArg(1, sizeof(int), &scalar1);
Samplekernel.setArg(2, sizeof(int), &scalar2);
Samplekernel.setArg(3, sizeof(int), &scalar3);

奇怪的是,当我添加...

if(scalar1 != 1) scalar1 = 1;
if(scalar2 != 2) scalar2 = 2;
if(scalar3 != 3) scalar3 = 3;

...在双 for 循环之前的内核中,输出是正确的。

我在 Nvidia K20m GPU、OpenCL 1.1 版上运行我的程序。当我在 Nvidia C2075 上运行我的代码时,一切似乎都运行良好......

有人知道问题可能是什么吗?看起来该值未正确复制或被覆盖,但我没有在 for 循环之前访问该值...

提前致谢!

4

1 回答 1

2

我看起来你正在将一个指向 int 的指针传递给 setArg

Samplekernel.setArg(1, sizeof(int), &scalar1);

然后,在你的内核参数列表中,你有整数值,而不是指针:

__kernel void sample_kernel(__global double *BufferA, int scalar1, ...

您可以在内核参数列表中使用指针,如下所示:

__kernel void sample_kernel(__global double *BufferA, global int *scalar1,

或者 - 这就是我的建议,因为我在 C++ 绑定规范中找不到您的 kernel.setArg (...) 版本,但由于某种原因仅在 khronos.org 上的实现中 - 像这样直接复制标量:

Samplekernel.setArg(1, scalar1);

这还有一个优点,即该变量在内核的私有内存空间中可用,而不是在全局空间中,就像您将缓冲区指定为参数时一样。

您使用的 Kernel::setArg 版本可能不会复制该值,但可能仅用于主机绑定内核,但我对此并不满意。

此外,您可能需要检查 setArg 的返回值是否存在错误。

于 2013-04-12T10:42:23.063 回答