1

我试图弄清楚我的 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]);
  }

现在,如果我作为testKernel函数的参数传递 lenght4和包含十六进制值的输入字符串3e2b,我希望它们被转换为十进制62并且43请参阅此表以了解十六进制 - >十进制转换)。

而且,如果我使用我的 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 中运行时才表现出来?

4

1 回答 1

1
char converted_message[converted_message_length];

这是标准 OpenCL 不支持的可变长度数组。它可能作为扩展在某些 OpenCL 实现上工作,但不可移植。

为数组指定固定大小或在主机上分配缓冲区。

于 2021-08-27T20:34:21.547 回答