CUDA矩阵复制

时间:2014-01-27 02:17:07

标签: cuda

我一直试图在简单的矩阵复制示例中理解线程和块索引模式 http://devblogs.nvidia.com/parallelforall/efficient-matrix-transpose-cuda-cc/

为什么我们在计算y时使用TILE_DIM作为步幅,因为我们知道块大小是(TILE_DIM * BLOCK_ROWS)。此外,我们通过强制每个线程执行TILE_DIM / BLOCK_ROWS副本来分摊计算。我尝试将Threads Per Block视为(4,1),将每网格块视为(2,2),方形矩阵宽度为8.我发现创建的偏移值也超过15,高于矩阵线性(1D)维度。如果可能,请帮助使用示例。我想看一些关于矩阵平铺与摊销的链接教程详细解释。

const int TILE_DIM = 32;
const int BLOCK_ROWS = 8;

__global__ void copy(float *odata, const float *idata)
{
  int x = blockIdx.x * TILE_DIM + threadIdx.x;
  int y = blockIdx.y * TILE_DIM + threadIdx.y;
  int width = gridDim.x * TILE_DIM;

  for (int j = 0; j < TILE_DIM; j+= BLOCK_ROWS)
  odata[(y+j)*width + x] = idata[(y+j)*width + x];
}

...

const int nx = 1024;
const int ny = 1024;

dim3 dimGrid(nx/TILE_DIM, ny/TILE_DIM, 1);
dim3 dimBlock(TILE_DIM, BLOCK_ROWS, 1);

....

copy<<<dimGrid, dimBlock>>>( ... );

1 个答案:

答案 0 :(得分:1)

  

为什么我们在计算TILE_DIM时使用y作为步幅,因为我们知道我们的块大小为TILE_DIM * BLOCK_ROWS

根据您的代码,您将1024x1024矩阵“平铺”到32x32个磁贴,每个32x32元素。这是通过按

定义网格大小来完成的
dim3 dimGrid(nx/TILE_DIM, ny/TILE_DIM, 1);

此外,您正在对每个4个子8x32子区域中的每个区块进行分区。这是通过

定义块大小来完成的
dim3 dimBlock(TILE_DIM, BLOCK_ROWS, 1);

正如您所注意到的,每个块都应该复制整个图块。通过使用xy的定义,将索引(y+j)*width + x重写为

y*width + j*width + x = 
    (blockIdx.y * TILE_DIM)*width + blockIdx.x * TILE_DIM +
    (j+threadIdx.y)*width + threadIdx

第一个词(blockIdx.y * TILE_DIM)*width + blockIdx.x * TILE_DIM标识索引为(blockIdx.y * TILE_DIM, blockIdx.x * TILE_DIM)的矩阵元素,而索引blockIdx.x又是由blockIdx.y(j+threadIdx.y)*width + threadIdx.x标识的拼贴的最高元素。第二个元素threadIdx.x,j+threadIdx.y标识通用切片中索引为threadIdx.x的元素。现在,请考虑0介于TILE_DIM-1threadIdx.y之间,而0介于BLOCK_ROWSfor之间。这解释了为什么您需要j+threadIdx.y循环,以便(0,TILE_DIM-1)可以跨越整个时间间隔{{1}}。