2017-01-15 9 views
0

Я работаю над простым алгоритмом параллельной редукции, чтобы найти минимальное значение в массиве и сталкиваюсь с каким-то интересным неопределенным поведением в моем алгоритме. Я запускаю 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 выполняет окончательное сокращение до завершения остальных ядер.

Есть ли у кого-нибудь еще какие-либо предложения или советы по отладке этой проблемы?

Спасибо заранее!

ответ

0

Проблема заключалась в том, что ядро ​​запускалось с одним потоком на рабочую группу, а барьеры работали только в рабочей группе. См. Этот ответ на аналогичный вопрос: Open CL no synchronization despite barrier