我需要进行如下计算:A [x] [y] = sum {从z = 0到z = n} {B [x] [y] [z] + C [x] [y] [z ]},其中矩阵A的维度为[height] [width],矩阵为B,C的维度为[height] [width] [n]。
使用以下内容将值映射到内存:
index = 0;
for (z = 0; z<n; ++z)
for(y = 0; y<width; ++y)
for(x = 0; x<height; ++x) {
matrix[index] = value;
index++;
}
我想每个块计算一个总和,因为每个块都有自己的共享内存。为了避免数据竞争,我使用atomicAdd,如下所示:
全局内存中的部分代码:
dim3 block (n, 1, 1);
dim grid (height, width, 1);
内核:
atomicAdd( &(A[blockIdx.x + blockIdx.y*gridDim.y]),
B[blockIdx.x + blockIdx.y*gridDim.y+threadIdx.x*blockDim.x*blockDim.y]
+ C[blockIdx.x + blockIdx.y*gridDim.y+threadIdx.x*blockDim.x*blockDim.y] );
我想使用共享内存来计算总和,然后将此结果复制到全局内存中。
我不知道如何使用共享内存来完成该部分。在每个块的共享内存中将只存储一个数字(求和结果)。如何将此数字复制到全局内存中的矩阵中的正确位置?
答案 0 :(得分:3)
您可能不需要共享内存或原子内存访问来执行您要求的求和。如果我已正确理解这一点,那么您的数据按列主顺序排列,因此逻辑运算是在输出矩阵中每个矩阵条目有一个线程,并让每个线程遍历输入矩阵的z轴,并在它们运行时求和。这个内核可能看起来像:
__global__ void kernel(float *A, const float *B, const float *C,
const int width, const int height, const int n)
{
int tidx = threadIdx.x + blockDim.x * blockIdx.x;
int tidy = threadIdx.y + blockDim.y * blockIdx.y;
if ( (tidx < height) && (tidy < width) ) {
int stride = width * height;
int ipos = tidx + tidy * height;
float * oval = A + ipos;
float sum = 0.f;
for(int z=0; z<n; z++, ipos+=stride) {
sum += B[ipos] + C[ipos];
}
*oval = sum;
}
}
对于width * height >= n
的列主要数据,此方法应该是最佳的。使用共享内存没有性能优势,也没有必要使用原子内存操作。如果你遇到width * height << n
问题,那么每次求和尝试逐块并行减少可能是有意义的。但是你没有说明问题的典型尺寸是什么。如果您的问题更像是后者,请发表评论,我可以在答案中添加基于缩减的示例内核。