摘要: OpenCL是否允许在内核函数中从指向结构的指针创建指针,并允许在同一内存块中的结构之后创建数据的字节偏移量?
我试图更好地理解OpenCL在指针和结构方面的局限性。我目前正在从事的一个项目涉及不同类型的信号节点的处理,这些节点可以从一个处理实例到下一个处理实例具有完全不同大小的状态数据。我首先从Linux低延迟计划FIFO实现开始,所以在处理线程时没有内存分配或系统调用,而是试图为最终的OpenCL实现做计划。
考虑到这一点,我开始设计算法,将所有状态数据分配为一个块,从一个结构开始,并有附加的数据结构和数组,小心数据类型的正确对齐。结构中的整数偏移量字段指示缓冲区中其他数据的字节位置。因此,从技术上讲,结构中没有任何指针在将数据从主机传递到设备时可能无法工作。但是,状态数据的结果大小将因合成节点而异,尽管一旦分配它们,其大小不会改变。我不确定这是否违反了OpenCL的“无可变长度结构”规则。
简单示例(伪OpenCL代码):
// Additional data following Node structure:
// cl_float fArray[fArrayLen];
// cl_uint iArray[iArrayLen];
typedef struct
{
cl_float val1;
cl_float val2;
cl_uint fArrayOfs;
cl_uint fArrayLen;
cl_uint iArrayOfs;
cl_uint iArrayLen;
...
} Node;
void
node_process (__global Node *node)
{
__global cl_float *fArray;
__global cl_uint *iArray;
// Construct pointers to arrays following Node structure
fArray = ((cl_uchar *)node) + node->fArrayOfs;
iArray = ((cl_uchar *)node) + node->iArrayOfs;
...
}
如果这是不可能的,是否有人建议定义复杂的数据结构,这些数据结构在本质上是动态的,而不传递几十个指向内核函数的指针?动态特性只在分配它们时才具有,而不是在内核进行处理时。我唯一能想到的其他选项是将处理节点状态定义为一个联合,并将附加的数据结构作为参数传递给内核函数,但是这可能会变成大量的函数参数。或者允许使用带有指针的__local结构?
发布于 2021-03-02 13:15:18
是的,这在OpenCL中是允许的(正如您提到的,只要您坚持对齐规则),您将需要非常小心:
第一,
fArray = ((cl_uchar *)node) + node->fArrayOfs;
^^^^^^^^^^
您在这里忽略了内存类型,请确保包含__global
或它默认为(IIRC) __private
,它直接将您带到行为未定义的地方。通常,我建议对所有指针声明和类型的内存类型保持显式,因为缺省值通常是不明显的。
第二,如果您计划在GPU上运行这个程序,如果相邻工作项的控制流和内存访问模式非常不同,那么您将面临一个糟糕的时间,性能方面的问题。我建议您在架构划分工作和设计数据结构的方式之前,阅读GPU供应商的OpenCL性能优化指南。
https://stackoverflow.com/questions/66413929
复制