关于在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
中的某些值将被覆盖,即您需要更长的共享内存阵列或者必须以另一种方式组织内核。
在共享内存和跨步循环中使用减少的最佳(最有效)方法是什么?
提前致谢。
答案 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。