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

时间:2016-03-24 19:25:21

标签: opencl shared-memory nvidia

我按照示例here创建了一个可变长度的本地内存数组。 内核签名是这样的:

__kernel void foo(__global float4* ex_buffer,
                 int ex_int,
                 __local void *local_var) 

然后我调用clSetKernelArg获取本地内存内核参数,如下所示:

clSetKernelArg(*kern, 2, sizeof(char) * MaxSharedMem, NULL)

通过查询MaxSharedMem设置CL_DEVICE_LOCAL_MEM_SIZE的位置。 然后在内核中我将分配的本地内存分成几个数组和其他数据结构,并按我认为合适的方式使用它们。所有这一切都适用于AMD(gpu和cpu)和英特尔设备。但是,在Nvidia上,当我将此内核排入队列然后在队列上运行CL_INVALID_COMMAND_QUEUE时,我收到错误clFinish

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

__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;
}

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

1 个答案:

答案 0 :(得分:2)

< p>对于那些感兴趣的人,我终于收到了Nvidia的解释。当通过void指针传入共享内存块时,实际对齐与指向double(8字节对齐)的指针的预期对齐不匹配。由于未对准,GPU设备抛出异常。 < / p为H. < p>正如其中一条评论指出的那样,解决问题的一种方法是让内核参数成为指向编译器将正确对齐至少8个字节(double,ulong等)的东西的指针。 < / p为H. < p>理想情况下,编译器会对设备特有的任何对齐问题负责,但因为在我的问题中有一个小内核中有一个隐式指针,我觉得它很混乱。 < / p为H. < p>一旦存储器被8字节对齐,对假定较短对齐(例如,ushort)的指针类型的强制转换就可以正常工作。因此,如果您像我一样链接内存分配,并且指针指向不同的类型,请确保指针指向内核签名中的最大类型。 < / p为H.