设置(标量)内核参数OpenCL后的值错误

设置(标量)内核参数OpenCL后的值错误,opencl,kernel,argument-passing,Opencl,Kernel,Argument Passing,我正在开发一个OpenCL程序,但是每次执行的输出都不同。我认为这与向内核传递参数有关,因为当我硬编码特定执行的值时,每次执行后的输出都是相似的 我的内核如下所示: __kernel void sample_kernel(__global double *BufferA, int scalar1, int scalar2, int scalar3, ...) { for(int i = -1*scalar1; i < scalar1; i++) { for(int

我正在开发一个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.
        }
    }
}
奇怪的是当我加上

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循环之前我无法访问该值


提前谢谢

看起来您正在将指向int的指针传递给setArg

Samplekernel.setArg(1, sizeof(int), &scalar1);
然后,在内核参数列表中,有int值,而不是指针:

__kernel void sample_kernel(__global double *BufferA, int scalar1, ...
您可以在内核参数列表中使用指针,如下所示:

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

或-----这就是我的建议,因为我在C++绑定规范中找不到你的Keln.StARGG(…)版本,但是由于一些原因,只有在kHRONSO.ORG上实现了,直接复制标量,比如::/P>

Samplekernel.setArg(1, scalar1);
这还有一个优点,即变量可以在内核的私有内存空间中使用,而不是在全局空间中使用,就像将缓冲区指定为参数一样

您正在使用的Kernel::setArg版本可能不会复制该值,但可能仅用于主机绑定的内核,但我不是舒尔的支持者


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

是否在不同的线程中使用相同的Samplekernel?是的。我尽可能多地启动内核线程。我指的是主机程序中的线程。clSetKernelArg不是线程安全的。不,我没有在不同的线程中使用它…这不太正确。您可以将指向int的指针传递给
setArg
,如果这样做,参数将作为标量传递,而不是指针,但必须在专用内存空间中声明,例如
private int scalar1
setArg
函数不会神奇地区分指针和标量,它只会检查参数是否是OpenCL内存对象,如果不是,只会将块内存复制到私有内存中,让开发人员负责确保复制到内核的内容能够被内核理解。至少我的C++绑定是这样做的……从我所理解的标准中的第5.5.4节,私有限定符实际上不会有任何区别,因为没有限定符的任何东西都是自动私有的,而且,我现在看到你是对的。setArg(1,scalar1)和setArg(1,sizeof(int)和scalar1)解析为相同的cl-call.Ah,感谢您的澄清。我更喜欢为内核参数显式地提供内存空间,不过这只是一种习惯。
Samplekernel.setArg(1, scalar1);