作为OpenCL内核参数的二维数组

9
非常直白的问题:如何将2D数组用作OpenCL内核参数?
常识建议使用 __kernel void main(__global <datatype> **<name>),然而编译器似乎对此想法并不感兴趣:kernel parameter cannot be declared as a pointer to a pointer
我是否忽略了显而易见的东西?或者我在这里做错了什么?
编辑:
主机(c++)数据结构如下: vector<vector<Element>>
其中Element是一个包含相同数组中子节点索引的结构体。基本上是指针。

在OpenCL中,您不能将指针作为全局变量传递。对于您的目的,图像/纹理是否可行?或者使用一维数组? - mfa
我正在传递一个树的数组,它们本身存储为结构体的数组,因此图像根本不适合我的目的。我可以考虑使用一维数组,但我不确定这是否可行。 - l'arbre
这些树是否平衡?它们能否被结构化为一个一维数组?如果必要,您可以多次调用内核并使用不同的参数。 - mfa
大多数答案中都隐含着但从未直接说明的是:vector<vector<Element>> 的元素在内存中不是连续的。 - Dithermaster
1个回答

13
你需要将这个二维数组化简成一个一维数组。
主机:
int array[50][50];
int * ptr_to_array_data = array[0];
int width = 50, height = 50;
cl_mem device_array = clCreateBuffer(/*context*/, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, 50 * 50 * sizeof(int), ptr_to_array_data, /*&err*/);
clSetKernelArg(/*kernel*/, 0, sizeof(cl_mem), &device_array);
clSetKernelArg(/*kernel*/, 1, sizeof(cl_int), &width);
clSetKernelArg(/*kernel*/, 2, sizeof(cl_int), &height);

设备:

kernel function(global int * array, int width, int height) {
    int id = get_global_id(0);
    int our_value = array[id];
    int x = id % width; //This will depend on how the memory is laid out in the 2d array. 
    int y = id / width; //If it's not row-major, then you'll need to flip these two statements.
    /*...*/
}

如果你的二维数组在内存中不是像我的例子那样连续存储的,那么你需要自己编写一个函数来确保整个内存以单个堆分配对象的形式连续存储。


据我所知,没有这样的功能。我也不建议使用图像进行此类数据处理,因为访问图像通常需要采样器,这会以一种鼓励错误和难以阅读代码的方式抽象化您的访问。 - Xirema
1
或者换个角度看,使用样本和专用函数访问图像可以避免您进行丑陋的数学计算以查找元素,使用单个内核支持许多不同的像素类型,允许边界、镜像或重复,并且如果需要,可以访问硬件双线性插值。 - Dithermaster
2
@Dithermaster如果你正在处理实际的图像数据,那么所有这些都非常有用。但是,如果你正在处理数据结构或非图像数据(正如OP所描述的),添加这些层复杂性只会带来微不足道的好处。 - Xirema

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接