按照 OpenCL 中的结构访问结构化数据

Accessing structured data following a struct in OpenCL

总结:OpenCL 是否允许在内核函数中从指向结构的指针和指向同一内存块中结构之后的数据的字节偏移量创建指针?

我试图更好地理解 OpenCL 在指针和结构方面的局限性。我目前正在进行的一个项目涉及处理不同类型的信号节点,从一个处理实例到下一个处理实例,这些节点的状态数据大小可能截然不同。我首先从 Linux CPU 低延迟 SCHED 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 结构?

是的,这在 OpenCL 中是允许的(只要您遵守对齐规则,就像您提到的那样),但是您需要非常小心:

首先,

fArray = ((cl_uchar *)node) + node->fArrayOfs;
           ^^^^^^^^^^

你错过了这里的内存类型,确保你包括 __global 或它默认为 (IIRC) __private 这将你直接带到未定义行为的领域。通常,我建议明确所有指针声明和类型的内存类型,因为默认值通常不明显。

其次,如果您计划 运行 在 GPU 上执行此操作,如果相邻工作项的控制流和内存访问模式非常不同,那么您在性能方面的表现会很糟糕。我建议在设计拆分工作和设计数据结构的方式之前阅读 GPU 供应商的 OpenCL 性能优化指南。