为什么我的CUDA程序的输出不可靠?

时间:2012-11-03 20:09:18

标签: cuda

我正在使用CUDA提供的编程指南自学CUDA。为了实践,我创建了一个简单的内核,用于确定数组的最大值并将其返回给CPU:

  __global__ void getTheMaximum(float* myArrayFromCPU, float* returnedMaximum) {
    // Store my current value in shared memory.
    extern __shared__ float sharedData[];
    sharedData[threadIdx.x] = myArrayFromCPU[threadIdx.x];

    // Iteratively calculate the maximum.
    int halfScan = blockDim.x / 2;
    while (halfScan > 0 && threadIdx.x < halfScan) {
      if (sharedData[threadIdx.x] < sharedData[threadIdx.x + halfScan]) {
        sharedData[threadIdx.x] = sharedData[threadIdx.x + halfScan];
      }
      halfScan = halfScan / 2;
    }

    // Put maximum value in global memory for later return to CPU.
    returnedMaximum[0] = sharedData[0];
  }

myArrayFromCPU是一个大小为1024的浮点值数组。returnedMaximum是一个包含单个项目的简单数组:计算出的最大值。

我对这个算法的想法是,它会迭代地确定最大值,因为它会将块大小的一半减去当前值。

但是,当我运行此代码时,输​​出的输出不可靠。返回的最大值会有所不同。这是为什么?单个算法如何每次都产生不同的值?

更新

我也只是在一个块上运行。我通过设置X = 1024的1维块大小来保证这一点。

1 个答案:

答案 0 :(得分:2)

不能保证整个块的所有线程都在同一时刻执行。这保证你只有一个warp(32个线程组)。

为了避免块内的并发危险 - 您可以使用__syncthreads()内部函数来停止到达它的线程,直到所有线程到达该点。 请注意,您不应将__syncthreads()放在分支代码中,否则您无法保证所有线程都能统一到达该位置。

尝试以下循环:

__syncthreads();
while (halfScan > 0) {
  if (threadIdx.x < halfScan) {
    if (sharedData[threadIdx.x] < sharedData[threadIdx.x + halfScan]) {
      sharedData[threadIdx.x] = sharedData[threadIdx.x + halfScan];
    }
  }
  __syncthreads();
  halfScan = halfScan / 2;
}

请注意,我从while循环中删除了条件threadIdx.x < halfScan,因为我希望所有线程在同一位置执行__syncthreads()且次数相同

此外,循环之前的__syncthreads()可能有助于确保在循环开始之前myArrayFromCPU的负载完成(对于所有线程)。