OpenCL 中的全局内存是不是连续

Posted

技术标签:

【中文标题】OpenCL 中的全局内存是不是连续【英文标题】:Is global memory contiguous in OpenCLOpenCL 中的全局内存是否连续 【发布时间】:2016-01-11 23:26:37 【问题描述】:

我是 OpenCL 新手,正在尝试使用 OpenCL 中的全局内存进行 2D 扫描。

我在输出数组中有一些无效值,这让人怀疑 如果全局内存是连续的。因为通过运行以下内核,我在输出数组中发现了一些垃圾值。

这是我的内核。输入和输出都是 8 x 8 二维数组。

#define SWAP(a,b) __global uint *tmp=a;a=b;b=tmp;
__kernel void 2dScan(
    const __global  uint * const input,
    __global  uint * const output,
    __global uint *lb,
    __global uint *lc
    )

    const uint x = get_global_id(0);
    const uint y = get_global_id(1);
    const uint xm = get_global_size(0);
    const uint ym = get_global_size(1);
    uint gs = get_global_size(0) * get_global_size(1);
    uint index = y * xm + x;

    lb[index] = lc[index] = input[index];
    barrier(CLK_GLOBAL_MEM_FENCE);

    for(uint s = 1; s < gs; s <<= 1) 
        if(index > (s-1)) 
            lc[index] = lb[index]+lb[index-s];
         else 
            lc[index] = lb[index];
        
        barrier(CLK_GLOBAL_MEM_FENCE);
        SWAP(lb,lc);
    
    output[index]= lb[index];


如果您能提供一些建议,非常感谢。

【问题讨论】:

我认为你的意思是“连续”。 【参考方案1】:

我有一个疑问,什么是垃圾价值?一个未初始化的还是不正确的?

在我看来,你的 for 循环有问题。您的访问不是确定性的,也就是说,您无法确定输出[2] 的结果。

例如,工作项 #2 在循环内执行 (s = 1):lc[2] = lb[2] + lb[1]; 好的,问题是:lb[1] 的值是否已被工作项 #1 修改?您的屏障同步了属于同一工作组的工作项。我认为lc[index] = lb[index]+lb[index-s]; 中的访问超出了工作组的“限制”,因为s 值导致了非确定性问题。

【讨论】:

非常感谢您的回答。我所说的垃圾值是指未初始化的值。现在我明白了问题所在。谢谢!【参考方案2】:

您正在覆盖每个工作项中的 lblc。因此结果是不确定的,因为 OpenCL 在全局项之间没有同步。 barrier(CLK_GLOBAL_MEM_FENCE); 在全局内存范围内同步本地工作组。

您将获得的结果基于计划模式,并且无法以任何方式预测。但是,它只会发生在本地组边界中。

你需要改变你的算法。

【讨论】:

感谢您的回答!现在我明白barrier(CLK_GLOCAL_MEM_FENCE); 不会同步全局项目。非常感谢!

以上是关于OpenCL 中的全局内存是不是连续的主要内容,如果未能解决你的问题,请参考以下文章

OpenCL 中的私有内存是不是有最大限制?

将全局内存用于(大)本地/私有温度。 OpenCL 中高效的数据结构

OpenCL 中的最佳本地/全局工作量

OpenCL - 全局内存读取性能优于本地

为啥 Cuda/OpenCL 的全局内存中没有银行冲突?

OpenCL中工作项和全局内存之间的内存传输?