CUDA:使用网格划分循环减少共享内存

时间:2014-08-08 04:03:50

标签: c memory cuda shared

关于在CUDA内核中共享内存中网格跨越循环和优化缩减算法的使用,我有以下问题。 想象一下,你有一维数组,其元素数多于网格中的线程数(BLOCK_SIZE * GRID_SIZE)。在这种情况下,您将编写此类内核:

#define BLOCK_SIZE (8)
#define GRID_SIZE (8)
#define N (2000)

// ...

__global__ void gridStridedLoop_kernel(double *global_1D_array)
{
    int idx = threadIdx.x + blockIdx.x * blockDim.x;
    int i;

    // N is a total number of elements in the global_1D_array array
    for (i = idx; i < N; i += blockDim.x * gridDim.x)
    {
        // Do smth...
    }
}

现在,您希望使用共享内存的减少来查找global_1D_array中的最大元素,上面的内核将如下所示:

#define BLOCK_SIZE (8)
#define GRID_SIZE (8)
#define N (2000)

// ...

__global__ void gridStridedLoop_kernel(double *global_1D_array)
{
    int idx = threadIdx.x + blockIdx.x * blockDim.x;
    int i;

    // Initialize shared memory array for the each block
    __shared__ double data[BLOCK_SIZE];

    // N is a total number of elements in the global_1D_array array
    for (i = idx; i < N; i += blockDim.x * gridDim.x)
    {
        // Load data from global to shared memory
        data[threadIdx.x] = global_1D_array[i];
        __syncthreads();

        // Do reduction in shared memory ...
    }

    // Copy MAX value for each block into global memory
}

很明显,data中的某些值将被覆盖,即您需要更长的共享内存阵列或者必须以另一种方式组织内核。 在共享内存和跨步循环中使用减少的最佳(最有效)方法是什么?

提前致谢。

1 个答案:

答案 0 :(得分:4)

记录使用网格跨越循环的减少here。参考幻灯片32,网格划分的循环如下所示:

unsigned int tid = threadIdx.x;
unsigned int i = blockIdx.x*(blockSize*2) + threadIdx.x;
unsigned int gridSize = blockSize*2*gridDim.x;
sdata[tid] = 0;
while (i < n){
  sdata[tid] += g_idata[i] + g_idata[i+blockSize];
  i += gridSize;
  }
__syncthreads();

请注意,while循环的每次迭代都会使索引增加gridSize,并且此while循环将继续,直到索引(i)超过(全局)数据大小({{1 }})。我们称之为网格跨越循环。在这个例子中,线程块局部缩减操作的其余部分不受网格大小循环的影响,因此只有&#34;前端&#34;显示。这种特殊的减少正在减少总和,但最大减少只是用以下的方式取代操作:

n

并且必须以类似的方式修改线程块级别的其余部分,用最大查找操作替换求和操作。

完整的并行缩减CUDA示例代码可作为任何完整cuda示例安装的一部分提供,或here