CUDA转OpenCL:在OpenCL中,(blockIdx.x + blockIdx.y * gridDim.x)* blockDim.x + threadIdx.x的等效表达式是什么?

4
我是一名OpenCL初学者,试图将一个简单的CUDA函数转换为OpenCL。在CUDA函数中,他们使用了下面的代码片段来获取操作的索引,
int id = (blockIdx.x + blockIdx.y*gridDim.x) * blockDim.x + threadIdx.x;

get_global_id(0)在OpenCL中是否相当于上述内容?
int id = get_global_id(0);

3
简短的回答是否定的。你还有其他想要得到除了是/否的回答吗? - talonmies
@talonmies 如果不行,我想找到另一种方法来实现这个目标。 - Avis
1个回答

11

我对CUDA不熟悉(只熟悉OpenCL),但看起来以下几个函数是等价的:

  • get_group_id(uint dimindx)blockIdx.[xyz]
  • get_local_size(uint dimindx)blockDim.[xyz]
  • get_local_id(uint dimindx)threadIdx.[xyz]
  • get_num_groups(uint dimindx)gridDim.[xyz]

其中dimindx为0、1或2,分别对应.x.y.z

get_global_id(0)get_group_id(0) * get_local_size(0) + get_local_id(0)是相同的,因此如果假设上述等价性是正确的,则它将与blockIdx.x * blockDim.x + threadIdx.x相同。(对于索引1和.y、索引2和.z同理)

要获取相同的ID值,您可能需要像这样:

int id = get_group_id(1) * get_global_size(0) + get_global_id(0);

请注意,原始的CUDA代码明确没有考虑 threadIdx.y。我猜测这可能是因为你的blockDim.y为1,或者因为你真的想要获得块中最顶部的项(而不是与当前线程对应的项)。

更常见的场景可能是获取当前工作项在包含2D元素数组的缓冲区中的数组中的索引:

int id = get_global_id(1) * get_global_size(0) + get_global_id(0);

如果 get_local_size(1) 为 1,则此表达式与先前的表达式等价。 (块高度为1。)

以上所有内容都假定您已使用与 CUDA 中相同的工作组(块)和全局维度排队内核。


我不确定你的最后一个表达式是否正确,get_global_id(1) 应该改为 get_group_id(1) - talonmies
@talonmies 看起来你在深入检查问题方面是正确的。我会修复它 - 尽管我怀疑在提问者的情况下,块大小在y方向上可能为1,否则似乎很奇怪能够获得ID。 - pmdj
@talonmies 我怀疑 get_global_id(1) * get_global_size(0) + get_global_id(0) 对其他人更有用,因此我已经添加了相关说明并纠正了原来的错误。 - pmdj

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