OpenCL ND-Range边界?

时间:2014-12-03 14:14:01

标签: opencl boundary

考虑执行向量加法的内核:

__kernel void vecAdd(__global double *a,
                     __global double *b,
                     __global double *c,
                     const unsigned int n)
{                                           
    //Get our global thread ID              
    int id = get_global_id(0);              

    //Make sure we do not go out of bounds  
    if (id < n)                             
        c[id] = a[id] + b[id];              
}

是否真的有必要将大小n传递给函数,并检查边界?

我在没有检查n的情况下看到了相同的版本。哪一个是正确的?

更一般地说,我想知道如果要处理的数据大小与用户定义的NR范围不同会发生什么。

是否会处理剩余的越界数据?

  • 是这样,怎么处理?
  • 如果没有,这是否意味着用户在编写内核时必须考虑边界?

OpenCL是否指定了这些内容?

由于

2 个答案:

答案 0 :(得分:2)

如果您不确定具有n个工作项的多个,则对n进行检查是个好主意。当你知道你只用n个工作项调用内核时,检查只占用处理周期,内核大小和指令调度程序的注意。

传递给内核的额外数据不会发生任何事情。虽然如果您在某些时候不使用数据,但您确实浪费时间将其复制到设备中。

我喜欢将内核的工作组和全局大小与要完成的工作完全无关。在这种情况下,我需要传递'n'。

例如:

__kernel void vecAdd(  __global double *a, __global double *b, __global double *c, const unsigned int n)
{                                           
    //Get our global thread ID and global size
    int gid = get_global_id(0);              
    int gsize = get_global_size(0);              

    //check vs n using for-loop condition
    for(int i=gid; i<n; i+= gsize){
        c[i] = a[i] + b[i];              
    }
}

该示例将采用n的任意值以及任何全局大小。每个工作项将处理每个第n个元素,从它自己的全局id开始。同样的想法也适用于工作组,有时候因为内存局部性而优于我列出的全局版本。

如果你知道n的值是常数,那么硬编码通常会更好(作为顶部的DEFINE)。这将允许编译器针对该特定值进行优化并消除额外参数。此类内核的示例包括:DFT / FFT处理,给定阶段的bitonic排序以及使用常量维度的图像处理。

答案 1 :(得分:0)

当主机代码指定工作组大小时,这是典型的,因为在OpenCL 1.x中,全局大小必须是工作组大小的倍数。因此,如果您的数据大小为1000且工作组大小为128,那么全局大小需要四舍五入到1024.因此检查。在OpenCL 2.0中,此要求已被删除。