Cuda 共享内存的模拟计算和数据加载:分片矩阵乘法的情况

Cuda 共享内存的模拟计算和数据加载:分片矩阵乘法的情况,cuda,Cuda,我想基于CUDA的共享内存示例编写一个矩阵乘法算法,它同时执行计算和数据加载。我的代码如下所示: float As[BLOCK_SIZE][BLOCK_SIZE]; float Bs[BLOCK_SIZE][BLOCK_SIZE]; As[ty][tx] = A[aBegin + wA * ty + tx]; Bs[ty][tx] = B[bBegin + wB * ty + tx]; for (int a = aBegin, b = bBegin; a <= aEnd; a += aSt

我想基于CUDA的共享内存示例编写一个矩阵乘法算法,它同时执行计算和数据加载。我的代码如下所示:

float As[BLOCK_SIZE][BLOCK_SIZE];
float Bs[BLOCK_SIZE][BLOCK_SIZE];
As[ty][tx] = A[aBegin + wA * ty + tx];
Bs[ty][tx] = B[bBegin + wB * ty + tx];
for (int a = aBegin, b = bBegin; a <= aEnd; a += aStep, b += bStep)
{
    __shared__ float A2s[BLOCK_SIZE][BLOCK_SIZE];
    __shared__ float B2s[BLOCK_SIZE][BLOCK_SIZE];
    A2s[ty][tx] = As[ty][tx];
    B2s[ty][tx] = Bs[ty][tx];
    __syncthreads();
    if (a+1 <= aEnd)
    {
        As[ty][tx] = A[a+1 + wA * ty + tx];
        Bs[ty][tx] = B[b+1 + wB * ty + tx]; 
    }
#pragma unroll
    for (int k = 0; k < BLOCK_SIZE; ++k)
    {
         Csub += A2s[ty][k] * B2s[k][tx];
    }   
    __syncthreads();
}
浮动为[BLOCK_SIZE][BLOCK_SIZE];
浮动Bs[块大小][块大小];
As[ty][tx]=A[aBegin+wA*ty+tx];
Bs[ty][tx]=B[bBegin+wB*ty+tx];

对于(int a=aBegin,b=bBegin;a您应该避免将数据
a
b
移动到本地数组
As
Bs
,即

As[ty][tx] = A[aBegin + wA * ty + tx];
Bs[ty][tx] = B[bBegin + wB * ty + tx];
A2s[ty][tx] = A[aBegin + wA * ty + tx];
B2s[ty][tx] = B[bBegin + wB * ty + tx];
您可以直接将它们移动到共享内存
A2s
B2s
,即

As[ty][tx] = A[aBegin + wA * ty + tx];
Bs[ty][tx] = B[bBegin + wB * ty + tx];
A2s[ty][tx] = A[aBegin + wA * ty + tx];
B2s[ty][tx] = B[bBegin + wB * ty + tx];
此外,数据也会加载

As[ty][tx] = A[a+1 + wA * ty + tx];
Bs[ty][tx] = B[b+1 + wB * ty + tx]; 
似乎没有被开发

最后,您应该将共享内存数组的声明移到
for
循环之外,并且还缺少对输出矩阵的最终赋值

尝试以下方法:

__global__ void TiledMatrixMultiplicationKernel(float* A, float* B, float* C, int Width)
{
    __shared__float As[BLOCK_SIZE][BLOCK_SIZE];
    __shared__float Bs[BLOCK_SIZE][BLOCK_SIZE];
    int bx = blockIdx.x; int by = blockIdx.y;
    int tx = threadIdx.x; int ty = threadIdx.y;
    int Row = by * BLOCK_SIZE + ty;
    int Col = bx * BLOCK_SIZE + tx;
    float Csub = 0;
    for (int m = 0; m < Width/BLOCK_SIZE; ++m) {
    As[ty][tx] = A[Row*Width + (m*BLOCK_SIZE + tx)];
    Bs[ty][tx] = B[Col + (m*BLOCK_SIZE + ty)*Width];
    __syncthreads();
    for (int k = 0; k < BLOCK_SIZE; ++k) {
       Csub += As[ty][k] * Bs[k][tx];
       __syncthreads();
    }
    C[Row*Width+Col] = Csub;
}
\uuuu全局\uuuu无效TiledMatrix多重应用内核(浮点*A、浮点*B、浮点*C、整数宽度)
{
__共享浮点数为[块大小][块大小];
__共享浮点数Bs[块大小][块大小];
int bx=blockIdx.x;int by=blockIdx.y;
int tx=threadIdx.x;int ty=threadIdx.y;
int Row=按*块大小+ty;
int Col=bx*块大小+tx;
浮点数Csub=0;
用于(int m=0;m
一个技巧:避免使用本地内存(当您在内核中定义一个数组而没有
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,它的速度和全局内存一样慢。我正在考虑将数组存储在寄存器中-我不能在所有4个数组上使用共享数据,因为编译器返回错误,因为分配了太多共享数据。我发布的代码只是部分的,这就是为什么整个算法的某些关键部分丢失的原因。就我所理解的代码而言,它将丢失完美地利用负载计算序列中的共享数据。我仍然试图实现的是负载计算/加载下一个数据序列,以覆盖下一部分数据的数据负载下的计算。我假设一些线程将在现有数据上执行计算,而其他线程将仍然/已经在为e下一个循环steps@Matt我不清楚如何将计算与内存加载重叠。上述代码是使用共享内存的平铺矩阵乘法的标准实现。在此实现中,每个线程将相应的全局内存矩阵元素加载到相应的共享内存矩阵位置。threads然后同步。最后,每个线程计算输出矩阵的一个元素。每个输出矩阵元素都需要输入矩阵的完整对应行和列的知识,这意味着它们应该已经在共享内存中。@相反,如果要加载并同时累积所需的向量-向量乘法结果,那么您可能应该使用原子操作,然后将代码序列化。