【发布时间】:2021-09-21 02:11:03
【问题描述】:
我试图弄清楚我的 OpenCL 内核函数中发生的奇怪行为。我基本上是在尝试将包含十六进制的字符串转换为包含十进制表示的字符串,但是由于我无法理解的原因,使用 GPU 和 CPU 运行相同的内核会产生不同的结果。
内核如下所示:
// yes, there's no result defined for the moment
__kernel void testKernel(__global uint message_length, __global char *message) {
size_t converted_message_length = message_length / 2;
char converted_message[converted_message_length];
// (1) hex to decimal conversion
for (size_t idx = 0, j = 0; idx < converted_message_length; idx++, j++) {
converted_message[idx] = (message[j] & '@' ? message[j] + 9 : message[j]) << 4;
j++;
converted_message[idx] |= (message[j] & '@' ? message[j] + 9 : message[j]) & 0xF;
printf("converted '%c%c' into '%i'\n", message[j - 1], message[j], converted_message[idx]);
}
// (2) this should be redundant, since I already print the content...
// but actually behaves differently with different device (CPU/GPU)
for (size_t idx = 0, j = 0; idx < converted_message_length; idx++, j++) {
printf("converted_message[%i]: '%i'\n", idx, converted_message[idx]);
}
现在,如果我将长度4 作为testKernel 函数的参数传递,并输入包含十六进制值3e2b 的字符串,我希望它们被转换为十进制62 和43 (@987654321 @ 用于十六进制 -> 十进制转换)。
而且,如果我使用我的 CPU(Intel(R) Core(TM) i9-9880H)运行内核,我确实可以看到以下转换发生:
converted '3e' into '62'
converted '2b' into '43'
converted_message[0]: '62'
converted_message[1]: '43'
但是,如果我使用我的 GPU (AMD Radeon Pro 5500M) 运行同样的内核,我会看到以下结果:
converted '3e' into '62'
converted '2b' into '43'
converted_message[0]: '0' <-- why it is 0 ???
converted_message[1]: '0' <-- why it is 0 ???
似乎converted_message 已成功写入循环(1),但是当我进入(2) 循环时,它的值会丢失。这怎么可能?是不是 OpenCL 在后台执行了一些奇怪的优化,只有在 GPU 中运行时才会显现出来?
【问题讨论】:
-
内核是如何调度的?
-
我曾经在同一设备上遇到过这样的问题,但使用不同的驱动程序,尽管使用浮点编译器可以更改操作顺序,因此舍入错误可能会有所不同。但是,整数运算不应该出现不同的结果。我怀疑一台设备上的内存没有正确分配/初始化。