Функция ядра OpenCL дает разные результаты при работе на разных устройствах (CPU против GPU)

#opencl #opencl-c

Вопрос:

Я пытаюсь разобраться в странном поведении, происходящем в моей функции ядра 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] amp; '@' ? message[j]   9 : message[j]) << 4;
    j  ;
    converted_message[idx] |= (message[j] amp; '@' ? message[j]   9 : message[j]) amp; 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 функции длину 4 и входную строку , содержащую шестнадцатеричное значение 3e2b , я ожидаю, что они будут преобразованы в десятичные 62 числа и 43 (см. Эту таблицу для преобразования в шестнадцатеричное> десятичное).

И, если я запускаю ядро, используя свой процессор (Intel(R) Core(TM) i9-9880H), действительно, я вижу, как происходит следующее преобразование:

 converted '3e' into '62'
converted '2b' into '43'
converted_message[0]: '62'
converted_message[1]: '43'
 

Однако, если я запущу это же ядро с помощью своего графического процессора (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 выполняет какую-то странную оптимизацию под капотом, которая проявляется только при работе на графическом процессоре ?

Комментарии:

1. Как запланировано ядро?

2. У меня однажды были такие проблемы на том же устройстве, но с другим драйвером, хотя и с плавающей точкой, где компилятор может изменять порядок операций, поэтому ошибки округления могут быть разными. Однако различные результаты не должны быть возможны с целочисленными операциями. Я подозреваю, что на одном устройстве память неправильно выделена/инициализирована.

Ответ №1:

 char converted_message[converted_message_length];
 

Это массив переменной длины, который не поддерживается в стандартном OpenCL. Он может работать в некоторых реализациях OpenCL в качестве расширения, но не является переносимым.

Укажите фиксированный размер массива или выделите буфер на хосте.

Комментарии:

1. хорошо подмечено, большое спасибо, что указали на ссылку!