Nvidia上opencl共享内存的动态分配

Nvidia上opencl共享内存的动态分配,opencl,shared-memory,nvidia,Opencl,Shared Memory,Nvidia,下面的示例创建了一个可变长度的本地内存阵列。 内核签名如下所示: __kernel void foo(__global float4* ex_buffer, int ex_int, __local void *local_var) 然后我调用clSetKernelArg以获取本地内存内核参数,如下所示: clSetKernelArg(*kern, 2, sizeof(char) * MaxSharedMem, NULL)

下面的示例创建了一个可变长度的本地内存阵列。 内核签名如下所示:

__kernel void foo(__global float4* ex_buffer,
                 int ex_int,
                 __local void *local_var) 
然后我调用
clSetKernelArg
以获取本地内存内核参数,如下所示:

clSetKernelArg(*kern, 2, sizeof(char) * MaxSharedMem, NULL)
其中,
MaxSharedMem
是通过查询
CL\u设备\u本地\u内存大小设置的。
然后在内核内部,我将分配的本地内存拆分为几个数组和其他数据结构,并在我认为合适的情况下使用它们。所有这些都适用于AMD(gpu和cpu)和Intel设备。但是,在Nvidia上,当我将此内核排入队列,然后在队列上运行
clFinish
时,我会收到错误
CL\u INVALID\u命令\u QUEUE

这是一个生成上述错误的简单内核(本地工作大小为32):


如果我在本地内存中静态分配相同的数组和数据结构,内核运行良好。有人能为这种行为提供解释和/或解决办法吗?

对于那些感兴趣的人,我终于收到了Nvidia的解释。当共享内存块通过空指针传入时,实际对齐方式与指向double(8字节对齐)的指针的预期对齐方式不匹配。由于未对齐,GPU设备引发异常

正如其中一条评论所指出的,避免这个问题的一种方法是让内核参数成为一个指针,指向编译器将正确对齐至少8个字节的内容(double、ulong等)

理想情况下,编译器将负责特定于设备的任何对齐问题,但由于在我的问题中的小内核中有一个隐式指针,我认为它会被混淆


一旦内存是8字节对齐的,则转换为假定较短对齐的指针类型(例如ushort)将不会出现问题。因此,如果您像我这样链接内存分配,并且指针指向不同的类型,请确保指针指向内核签名中最大的类型

您正在使用/获取的
MaxSharedMem
的实际值是多少?如果将
MaxSharedMem
变量减小到更小的值,比如1000,会发生什么?主机不是C空间,是吗?SIZEOF(CHAR)2主机是C++。code>MaxSharedMem
对于我正在测试的卡是48000,即quadro K1000M。我尝试将其设置为较小的值,但没有效果。唯一能让我避免
CL\u INVALID\u COMMAND\u QUEUE
错误的是在本地mem中静态分配我的所有数据结构,这对我的内核来说几乎是不可行的。抱歉,卡是quadro 1000M,而不是K1000MPerhaps。您应该展示一个不起作用的简短完整示例。是我的样本,从vector add样本中稍作修改,该样本似乎在NVIDIA K40c上正确运行。感谢您回来并分享详细信息以帮助他人。谢谢您,也有同样的问题,很高兴您在此处发布了解决方案。非常有用。
__kernel 
void s_Kernel(const unsigned int N, __local void *shared_mem_block ) 
{
    const ushort thread_id = get_local_id(0);   
    __local double *foo = shared_mem_block;
    __local ushort *bar = (__local ushort *) &(foo[1000]);


    foo[thread_id] = 0.;
    bar[thread_id] = 0;
}