Я работаю над простым алгоритмом параллельной редукции, чтобы найти минимальное значение в массиве и сталкиваюсь с каким-то интересным неопределенным поведением в моем алгоритме. Я запускаю Intel OpenCL 1.2 на Ubuntu 16.04.OpenCL неопределенное поведение в параллельном алгоритме сокращения
Следующее ядро, что я пытаюсь запустить, которая в настоящее время дает мне неправильный ответ:
__kernel void Find_Min(int arraySize, __global double* scratch_arr, __global double* value_arr, __global double* min_arr){
const int index = get_global_id(0);
int length = (int)sqrt((double)arraySize);
int start = index*length;
double min_val = INFINITY;
for(int i=start; i<start+length && i < arraySize; i++){
if(value_arr[i] < min_val)
min_val = value_arr[i];
}
scratch_arr[index] = min_val;
barrier(CLK_GLOBAL_MEM_FENCE);
if(index == 0){
double totalMin = min_val;
for(int i=1; i<length; i++){
if(scratch_arr[i] < totalMin)
totalMin = scratch_arr[i];
}
min_arr[0] = totalMin;
}
}
Когда в положить в массив, который является {0, -1, -2, -3, -4, -5, -6, -7, -8} заканчивается возвратом -2.
Вот где неопределенное поведение приходит Когда я запускаю следующее ядро с PRINTF заявление перед барьером я получить правильный ответ (-8):.
__kernel void Find_Min(int arraySize, __global double* scratch_arr, __global double* value_arr, __global double* min_arr){
const int index = get_global_id(0);
int length = (int)sqrt((double)arraySize);
int start = index*length;
double min_val = INFINITY;
for(int i=start; i<start+length && i < arraySize; i++){
if(value_arr[i] < min_val)
min_val = value_arr[i];
}
scratch_arr[index] = min_val;
printf("setting scratch[%i] to %f\n", index, min_val);
barrier(CLK_GLOBAL_MEM_FENCE);
if(index == 0){
double totalMin = min_val;
for(int i=1; i<length; i++){
if(scratch_arr[i] < totalMin)
totalMin = scratch_arr[i];
}
min_arr[0] = totalMin;
}
}
Единственное, что я могу думать о что может случиться, что я неправильно использую команду барьера и все, что делает printf, вызывает задержку в ядре, которая каким-то образом синхронизирует вызовы, чтобы они все завершили до этапа окончательного восстановления. Но без printf ядро 0 выполняет окончательное сокращение до завершения остальных ядер.
Есть ли у кого-нибудь еще какие-либо предложения или советы по отладке этой проблемы?
Спасибо заранее!