CUDA矩阵副本

CUDA矩阵副本,cuda,Cuda,我一直在试图理解简单矩阵复制示例中的线程和块索引模式 既然我们知道块的大小是(TILE_DIM*Block_行),为什么在计算y时使用TILE_DIM作为步长。此外,我们还通过强制每个线程执行TILE\u DIM/BLOCK\u行拷贝来摊销计算。我尝试将每个块的线程视为(4,1),将每个网格的块视为(2,2),正方形矩阵宽度为8。我发现创建的偏移值也超过了矩阵线性(1D)维度之上的15。如果可能的话,请帮忙举个例子。我想看到一些详细解释矩阵平铺的链接教程 const int TILE_DIM

我一直在试图理解简单矩阵复制示例中的线程和块索引模式

既然我们知道块的大小是(TILE_DIM*Block_行),为什么在计算y时使用TILE_DIM作为步长。此外,我们还通过强制每个线程执行TILE\u DIM/BLOCK\u行拷贝来摊销计算。我尝试将每个块的线程视为(4,1),将每个网格的块视为(2,2),正方形矩阵宽度为8。我发现创建的偏移值也超过了矩阵线性(1D)维度之上的15。如果可能的话,请帮忙举个例子。我想看到一些详细解释矩阵平铺的链接教程

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>>>( ... );
const int TILE_DIM=32;
const int BLOCK_ROWS=8;
__全局无效副本(浮点*odata,常量浮点*idata)
{
int x=blockIdx.x*TILE_DIM+threadIdx.x;
int y=块IDX.y*平铺尺寸+螺纹IDX.y;
int width=gridDim.x*TILE\u DIM;
对于(int j=0;j
既然我们知道块大小是
TILE\u DIM*block\u ROWS
,为什么在计算
y
时要使用
TILE\u DIM
作为步长

根据您的代码,您正在将
1024x1024
矩阵“平铺”到
32x32
平铺中,每个
32x32
元素。这是通过定义网格大小来完成的

dim3 dimGrid(nx/TILE_DIM, ny/TILE_DIM, 1);
此外,您正在将每个磁贴划分为大小为
8x32
4
子文件。这是通过定义块大小来完成的

dim3 dimBlock(TILE_DIM, BLOCK_ROWS, 1);
正如您所注意到的,每个块都应该复制一个完整的平铺。通过引用
x
y
的定义,将索引
(y+j)*宽度+x
重写为

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

第一项
(blockIdx.y*TILE\u DIM)*width+blockIdx.x*TILE\u DIM
用索引
(blockIdx.y*TILE\u DIM,blockIdx.x*TILE\u DIM)
标识矩阵元素,后者又是
blockIdx.x
blockIdx.y
标识的最上面的元素。第二个元素
(j+threadIdx.y)*width+threadIdx.x
标识通用分幅内索引为
threadIdx.x,j+threadIdx.y
的元素。现在,考虑<代码> StudiaDX.x/Cux>介于<代码> 0 和<代码> TILYDIM-1之间,而<代码> SudiaDyx.y>代码>范围在<代码> 0 和<代码> BuffixReals>代码>中。这解释了为什么需要
for
循环,以便
j+threadIdx.y
可以跨越整个间隔
(0,TILE\u DIM-1)

非常感谢Talongies更新代码。我很抱歉没有把相关的代码以适当的形式。我仍然无法获得线程在按元素复制期间的工作情况。关于您自己的示例,您选择了多少
TILE\u DIM
?非常感谢Jackolanten,我现在清楚地了解了它的工作原理。为了澄清(j+threadIdx.y,threadIdx.x)索引部分,该索引是否引用矩阵的列元素的TILE DIM/BLOCK行数?在
(j+threadIdx.y,threadIdx.x)
索引中,
(threadIdx.y,threadIdx.x)
寻址子TILE的特定元素,而
j
寻址子TILE,因此,它充当偏移量。您必须想象一个子图块,例如对应于
j=1
,位于对应于
j=2
的子图块的顶部。这样,
threadIdx.y
是通用子分幅内的“相对”行索引,而
j+threadIdx.y
是通用分幅内的“绝对”行索引。对于列,您只有一个“绝对”列索引
threadIdx.x
,因为您只有沿行的子平铺。我推测,我们通过将块大小取为平铺大小的1/4来摊销计算。但除此之外,我们还使用此方法提供联合访问。我的观点正确吗?