Memory 如何在OpenCL中声明本地内存?

Memory 如何在OpenCL中声明本地内存?,memory,opencl,Memory,Opencl,我正在运行下面的OpenCL内核,其二维全局工作大小为1000000 x 100,本地工作大小为1 x 100 __kernel void myKernel( const int length, const int height, and a bunch of other parameters) { //declare some local arrays to be shared by all 100 work item in thi

我正在运行下面的OpenCL内核,其二维全局工作大小为1000000 x 100,本地工作大小为1 x 100

__kernel void myKernel(
        const int length, 
        const int height, 
        and a bunch of other parameters) {

    //declare some local arrays to be shared by all 100 work item in this group
    __local float LP [length];
    __local float LT [height];
    __local int bitErrors = 0;
    __local bool failed = false;

    //here come my actual computations which utilize the space in LP and LT
}
但是,它拒绝编译,因为编译时不知道参数
length
height
。但我根本不清楚如何正确地做到这一点。我应该在memalloc中使用指针吗?如何处理这个问题,使内存只为整个工作组分配一次,而不是每个工作项分配一次


我只需要两个浮点数组,一个int和一个boolean,在整个工作组中共享(所以所有100个工作项)。但是我找不到任何正确的方法…

这相对简单,您可以将本地数组作为参数传递给内核:

kernel void myKernel(const int length, const int height, local float* LP, 
                     local float* LT, a bunch of other parameters) 
然后,将kernelargument设置为
NULL
,并且
大小
等于要为参数分配的大小(以字节为单位)。因此,它应该是:

clSetKernelArg(kernel, 2, length * sizeof(cl_float), NULL);
clSetKernelArg(kernel, 2, height* sizeof(cl_float), NULL);
本地内存总是由工作组共享的(而不是私有的),因此我认为
bool
int
应该可以,但如果不能,也可以将它们作为参数传递

与您的问题并不相关(也不一定相关,因为我不知道您计划在什么硬件上运行此功能),但至少GPU并不特别喜欢不是特定二次幂倍数的工作大小(我认为nvidia为32,amd为64),这意味着可能会创建包含128项的工作组,其中最后28个基本上被浪费掉了。因此,如果您在gpu上运行opencl,那么直接使用大小为128的工作组(并适当更改全局工作大小)可能有助于提高性能


作为旁注:我一直不明白为什么每个人对
内核使用下划线变量,本地和全局
,对我来说似乎更难看。

您不必在内核之外分配所有本地内存,特别是当它是一个简单的变量而不是数组时

代码无法编译的原因是OpenCL不支持本地内存初始化。这在文档()中指定。这在CUDA()中也不可行



附言:灰熊的回答很好,如果我能把它作为评论发布,那就更好了,但我受到声誉政策的限制。抱歉。

您也可以这样声明阵列:

__local float LP[LENGTH];
并将长度作为定义传递给内核编译

int lp_size = 128; // this is an example; could be dynamically calculated
char compileArgs[64];
sprintf(compileArgs, "-DLENGTH=%d", lp_size);
clBuildProgram(program, 0, NULL, compileArgs, NULL, NULL);

六羟甲基三聚氰胺六甲醚。。。那么,我应该如何解决这个工作组大小问题呢?100是一个标称值,它可以根据问题的具体情况而变化,但我需要全局输入的每个1x100子块的这些本地内存变量。我假设如果一个子块不是一个工作组,就没有办法使一个变量在其适当的1x100子块之间共享?(至于旁注,我从来没有尝试过没有_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?我可以沿着
clSetKernelArg(kernel,2,length*local\u work\u size[0]*sizeof(cl\u float),NULL)的行传递一些内容错误:变量“bitErrors”可能没有初始化
。如果我用上面的本地语句替换它,我会得到
错误:无法在命名地址空间中分配参数
。当然,我可以将其设置为长度为1的数组,但这并不是最漂亮的解决方案…:-)@user1111929:没错,您只能在工作组内共享变量。我刚才提到了,以防你改变你的工作尺寸。而将本地数组作为一维传递确实是一种方法,opencl并不真正支持嵌套指针。关于
bool
int
:我的意思是,如果它不是那样工作的话,就把它作为指针传递。我相信第二个
clSetKernelArg()
调用的第二个参数应该是
3
。如前所述,这将设置相同的参数两次。了解这一点很有用,但并不能解决如何在运行时(而不是在编译时)动态分配的问题。@MasterHD OpenCL代码可以(而且大多数简单的示例确实是)在运行时编译,因此这个答案确实解决了这个问题。