使用CPU时出现OpenCL segfault

使用CPU时出现OpenCL segfault,opencl,Opencl,我正在使用OpenCL实现一个FFT算法(特别是OpenCL中的算法)。它在两个不同的NVIDIA GPU(特斯拉K20c和GeForce GTX 650)上运行良好,但在我的Intel CPU上运行时会出现分段错误 我已经在内核代码中找到了问题所在,但没有意义。只有两行代码在包含时出错,这两行代码是下一块中最后两次写入本地内存。没有其他写入内存会导致CPU出现问题,也不会导致GPU出现问题 __kernel void fft_init(__global float2 *g_data, __lo

我正在使用OpenCL实现一个FFT算法(特别是OpenCL中的算法)。它在两个不同的NVIDIA GPU(特斯拉K20c和GeForce GTX 650)上运行良好,但在我的Intel CPU上运行时会出现分段错误

我已经在内核代码中找到了问题所在,但没有意义。只有两行代码在包含时出错,这两行代码是下一块中最后两次写入本地内存。没有其他写入内存会导致CPU出现问题,也不会导致GPU出现问题

__kernel void fft_init(__global float2 *g_data, __local float2 *l_data, 
                   uint points_per_group, uint size, int dir) {

    uint4 br, index;
    uint points_per_item, g_addr, l_addr, i, fft_index, stage, N2;
    float2 x1, x2, x3, x4, sum12, diff12, sum34, diff34;

    points_per_item = points_per_group/get_local_size(0);
    l_addr = get_local_id(0) * points_per_item;
    g_addr = get_group_id(0) * points_per_group + l_addr;

    for(i=0; i<points_per_item; i+=4) {

     ...

        l_data[l_addr] = sum12 + sum34;
        l_data[l_addr+1] = diff12 + diff34;
        l_data[l_addr+2] = sum12 - sum34;
        l_data[l_addr+3] = diff12 - diff34; 

        l_addr+= 4;
}
\uuuuuu内核无效fft\uInit(\uuuuu全局浮点2*g\u数据,\uuuuu本地浮点2*l\u数据,
单位点数(单位分组、单位大小、单位方向){
uint4-br,指数;
每个项目的单位点数,g地址,l地址,i,fft索引,阶段,N2;
浮子2 x1、x2、x3、x4、sum12、diff12、sum34、diff34;
每个项目的点数=每个组的点数/获取本地大小(0);
l_addr=获取本地id(0)*每项积分;
g_addr=获取组id(0)*每个组的点数+l_addr;

对于(i=0;i我不完全确定它为什么工作,但我已经设法找到了一个解决方案。使用此程序,工作组大小需要为1024。两个NVIDIA卡已将此作为其最大工作组大小,但Intel CPU的最大工作组大小为4096(均由
clGetKernelWorkGroupInfo返回)(…CL_内核\u工作\u组\u大小…
。这就是GPU工作而CPU不工作的原因


同样,我也不知道为什么这样做可以使代码正常工作,但这是一个解决方案,我会接受它。

我猜您正在访问已分配的数组的末尾。您希望
l_data
数组的大小是多少(以字节为单位)在clSetKernelArg size参数中传递什么值?另外,clGetDeviceInfo for CL_DEVICE_LOCAL_MEM_size返回什么值?它适合吗?最后,如果本地内存的使用是固定大小的(而不是动态的),更好的形式是:
\u LOCAL float localBuffer[1024];
而不是使用内核参数。l_数据数组是GetDeviceInfo返回的LOCAL_MEM_大小的精确大小。在本例中,它是32768,这是我要传递给clSetKernelArg的数字。clSetKernelArg的指针参数为NULL,我现在就用它来看看是否有问题。本地内存是dynamic,不是固定的,因为我使用了设备可用的整个本地内存-但我将从内核内部研究一种方法。忽略我上面关于NULL参数的内容,我发现这是应该的方式。我发现在最小的情况下,l_addr决不会大于
get_local_id(0)
。由于每个组的工作项数量远小于本地内存大小,我无法理解为什么访问
l\u数据[l\u addr+3]
要访问超过数组末尾的数据。