实施CUDA减少的问题

时间:2016-08-13 06:03:54

标签: c parallel-processing cuda

我正在尝试在cuda中实现reduce,我在其中找到数组中的最大元素。我已经使用这个内核来找到最小值,并且它可以工作,但是当我试图找到最大值时它不起作用。我已经反复执行算法,无法找到错误。真的很感激任何帮助。 (另外,当我在那里取消注释print语句时,我得到了不同的输出,这也是一个非常令人头痛的问题....)

__global__
void findMaxAndMin(const float* const d_logLuminance, float* reduceCopy, int length, float* min_logLum, float* max_logLum){
    int idx = threadIdx.x + blockDim.x*blockIdx.x;
    if(idx >= length){
        return;
    }
    reduceCopy[idx] = d_logLuminance[idx];
    __syncthreads();

    //do a reduction with max

    for(int offset = 1;offset < length;offset = offset*2){
        if(idx % (offset*2) == 0){
            int compIdx = idx + offset;
            if(compIdx < length){
                float newVal = a_max(reduceCopy[idx], reduceCopy[compIdx]);
                if(idx == 0){
                    //printf("val %f \n", newVal);
                }
                __syncthreads();
                reduceCopy[idx] = newVal;
                __syncthreads();
            }
        }
        __syncthreads();
    }
    __syncthreads();
    if(idx == 0){
        *max_logLum = reduceCopy[0];
    }

}

1 个答案:

答案 0 :(得分:1)

代码有几个问题。如果它工作到最低限度,你很幸运。

  • 我假设您启动了多个块(使用blockIdx.x)。您在另一个块中重复使用一个块的结果 - reduceCopy[compIdx]可能由另一个块设置。您不能依赖于此:您无法预测块的执行顺序或同步它们。 __syncthreads()是一个仅在一个区块内有效的障碍!

  • if(idx >= length) return很危险,因为它会导致并非所有线程都会达到以下__syncthreads

  • 您在有条件的__syncthreads()内有if(compIdx < length)

  • a_max未定义。请记住始终包含最小的工作示例。我可以猜到该功能应该做什么,但也许还有潜伏在其中的另一个错误?

在我看来,你对理论上的并行缩减有很好的理解,但由于CUDA的特定行为,实现失败了。

我建议你阅读一些关于如何在CUDA上进行并行缩减的例子。