并行约简算法中的OpenCL未定义行为

并行约简算法中的OpenCL未定义行为,opencl,Opencl,我正在研究一个简单的并行简化算法,以找到数组中的最小值,并且在我的算法中遇到了一些有趣的未定义行为。我在Ubuntu 16.04上运行英特尔的OpenCL 1.2 以下内核是我正在尝试运行的内核,它目前给了我错误的答案: __kernel void Find_Min(int arraySize, __global double* scratch_arr, __global double* value_arr, __global double* min_arr){ const int i

我正在研究一个简单的并行简化算法,以找到数组中的最小值,并且在我的算法中遇到了一些有趣的未定义行为。我在Ubuntu 16.04上运行英特尔的OpenCL 1.2

以下内核是我正在尝试运行的内核,它目前给了我错误的答案:

__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;
    }
}
\uuuuuu内核void Find\u Min(int-arraySize、\uuuu-global double*scratch\u arr、\uuuu-global double*value\u arr、\uuuu-global double*Min\u arr){
const int index=get_global_id(0);
int length=(int)sqrt((double)arraySize);
int start=索引*长度;
双最小值=无穷大;

对于(int i=start;i而言,问题在于内核在启动时每个工作组有一个线程,而屏障仅在一个工作组内工作。请参阅对类似问题的回答:

__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;
    }
}