【问题标题】:Wrong value after setting (scalar) kernel argument OpenCL设置(标量)内核参数 OpenCL 后的值错误
【发布时间】:2013-02-18 16:09:49
【问题描述】:

我正在开发一个 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 循环之前访问该值...

提前致谢!

【问题讨论】:

  • 您是否在不同的线程中使用相同的 Samplekernel?
  • 是的。我为尽可能多的线程启动内核。
  • 我的意思是宿主程序中的线程。 clSetKernelArg 不是线程安全的。
  • 啊。不,我没有在不同的线程中使用它...

标签: opencl kernel argument-passing


【解决方案1】:

我看起来你正在将一个指向 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 的返回值是否有错误。

【讨论】:

  • 这不太正确。可以将指向 int 的指针传递给setArg,如果这样做,则参数作为标量而不是指针传递,必须在私有内存空间中声明,例如@ 987654326@。 setArg 函数不会神奇地区分指针和标量,它只是检查参数是否是 OpenCL 内存对象,如果不是,只需将块内存复制到私有内存中,将其留给开发人员负责确保复制到内核的任何内容都可以被内核理解。至少我的 C++ 绑定可以做到这一点……
  • 从我理解的标准中的 6.5.4 部分开始, private 限定符实际上没有任何区别,因为没有限定符的所有内容都是自动私有
  • 除此之外,我现在明白你是对的。 'setArg(1, scalar1)' 和 'setArg(1, sizeof(int), &scalar1)' 解析为同一个 cl 调用。
  • 啊,感谢您的澄清。我更喜欢始终为内核参数显式提供内存空间,但这只是一种习惯。
猜你喜欢
  • 2017-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-05
  • 1970-01-01
  • 2017-01-15
相关资源
最近更新 更多