考虑执行向量加法的内核:
__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是否指定了这些内容?
由于
答案 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中,此要求已被删除。