【发布时间】:2020-02-11 02:25:39
【问题描述】:
我知道 OpenCL 这些天相当空闲——尤其是 NVidia 的 CUDA 实现。也就是说,我认为我在 Nvidia 中发现了一个重大错误,我想看看其他人是否注意到了同样的问题。使用带有 C++ 绑定的 Linux Platform Version OpenCL 1.2 CUDA 10.1.0 我一直遇到 NDRange 顺序的各种问题,我终于有了一个可以明确重现该问题的简单内核:
void kernel test()
{
printf("G0:%d G1:%d G2:%d L0:%d L1:%d L2:%d\n",
get_global_id(0),
get_global_id(1),
get_global_id(2),
get_local_id(0),
get_local_id(1),
get_local_id(2));
}
如果我将这个内核加入 3 个维度:全局 (4,3,2) 和本地 (1,1,1):
queue.enqueueNDRangeKernel(kernel, cl::NullRange,
cl::NDRange(4, 3, 2),
cl::NDRange(1, 1, 1),
NULL, events);
它在 AMD/Intel 上随机正确输出以下内容(为清楚起见,随机输出排序):
G0:0 G1:0 G2:0 L0:0 L1:0 L2:0
G0:0 G1:0 G2:1 L0:0 L1:0 L2:0
G0:0 G1:1 G2:0 L0:0 L1:0 L2:0
G0:0 G1:1 G2:1 L0:0 L1:0 L2:0
G0:0 G1:2 G2:0 L0:0 L1:0 L2:0
G0:0 G1:2 G2:1 L0:0 L1:0 L2:0
G0:1 G1:0 G2:0 L0:0 L1:0 L2:0
G0:1 G1:0 G2:1 L0:0 L1:0 L2:0
G0:1 G1:1 G2:0 L0:0 L1:0 L2:0
G0:1 G1:1 G2:1 L0:0 L1:0 L2:0
G0:1 G1:2 G2:0 L0:0 L1:0 L2:0
G0:1 G1:2 G2:1 L0:0 L1:0 L2:0
G0:2 G1:0 G2:0 L0:0 L1:0 L2:0
G0:2 G1:0 G2:1 L0:0 L1:0 L2:0
G0:2 G1:1 G2:0 L0:0 L1:0 L2:0
G0:2 G1:1 G2:1 L0:0 L1:0 L2:0
G0:2 G1:2 G2:0 L0:0 L1:0 L2:0
G0:2 G1:2 G2:1 L0:0 L1:0 L2:0
G0:3 G1:0 G2:0 L0:0 L1:0 L2:0
G0:3 G1:0 G2:1 L0:0 L1:0 L2:0
G0:3 G1:1 G2:0 L0:0 L1:0 L2:0
G0:3 G1:1 G2:1 L0:0 L1:0 L2:0
G0:3 G1:2 G2:0 L0:0 L1:0 L2:0
G0:3 G1:2 G2:1 L0:0 L1:0 L2:0
这符合规范。但是,如果我使用 NVidia 调度具有相同尺寸的完全相同的内核,我会得到以下输出:
G0:0 G1:0 G2:0 L0:0 L1:0 L2:0
G0:0 G1:0 G2:0 L0:0 L1:1 L2:0
G0:0 G1:0 G2:1 L0:0 L1:0 L2:0
G0:0 G1:0 G2:1 L0:0 L1:1 L2:0
G0:0 G1:0 G2:2 L0:0 L1:0 L2:0
G0:0 G1:0 G2:2 L0:0 L1:1 L2:0
G0:1 G1:0 G2:0 L0:0 L1:0 L2:0
G0:1 G1:0 G2:0 L0:0 L1:1 L2:0
G0:1 G1:0 G2:1 L0:0 L1:0 L2:0
G0:1 G1:0 G2:1 L0:0 L1:1 L2:0
G0:1 G1:0 G2:2 L0:0 L1:0 L2:0
G0:1 G1:0 G2:2 L0:0 L1:1 L2:0
G0:2 G1:0 G2:0 L0:0 L1:0 L2:0
G0:2 G1:0 G2:0 L0:0 L1:1 L2:0
G0:2 G1:0 G2:1 L0:0 L1:0 L2:0
G0:2 G1:0 G2:1 L0:0 L1:1 L2:0
G0:2 G1:0 G2:2 L0:0 L1:0 L2:0
G0:2 G1:0 G2:2 L0:0 L1:1 L2:0
G0:3 G1:0 G2:0 L0:0 L1:0 L2:0
G0:3 G1:0 G2:0 L0:0 L1:1 L2:0
G0:3 G1:0 G2:1 L0:0 L1:0 L2:0
G0:3 G1:0 G2:1 L0:0 L1:1 L2:0
G0:3 G1:0 G2:2 L0:0 L1:0 L2:0
G0:3 G1:0 G2:2 L0:0 L1:1 L2:0
NVidia 对全局/局部维度的解释似乎是交错的,与规范不符。这似乎也不涉及 C++ 绑定。本地 ID 不应为零,而 get_global_id(1) 始终为零。
我知道 NVidia 不太关心 OpenCL,但这似乎是一个相当大的问题。其他人遇到这样的事情吗?这不是 printf 的同步问题。我在实际的数据用例中注意到了这一点,并且构建这个内核只是为了演示它。
【问题讨论】:
-
更正:这是 printf 的同步问题。