Memory 如何在OpenCL中声明本地内存?
我正在运行下面的OpenCL内核,其二维全局工作大小为1000000 x 100,本地工作大小为1 x 100Memory 如何在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
__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)的行传递一些内容但这是一个一维数组。可能最好是二维的,还是非二维的?另外,bool和int都不好,我得到一个错误:变量“bitErrors”可能没有初始化。如果我用上面的本地语句替换它,我会得到错误:无法在命名地址空间中分配参数。当然,我可以将其设置为长度为1的数组,但这并不是最漂亮的解决方案…:-)@user1111929:没错,您只能在工作组内共享变量。我刚才提到了,以防你改变你的工作尺寸。而将本地数组作为一维传递确实是一种方法,opencl并不真正支持嵌套指针。关于bool
和int
:我的意思是,如果它不是那样工作的话,就把它作为指针传递。我相信第二个clSetKernelArg()
调用的第二个参数应该是3
。如前所述,这将设置相同的参数两次。了解这一点很有用,但并不能解决如何在运行时(而不是在编译时)动态分配的问题。@MasterHD OpenCL代码可以(而且大多数简单的示例确实是)在运行时编译,因此这个答案确实解决了这个问题。