CUDA内核中全局内存加载事务的计算

时间:2015-11-19 06:56:35

标签: cuda

我对CUDA内核中全局内存加载事务的计算有疑问,因为profiled值与我的预期值不匹配。以下面的简单矩阵乘法代码为例:

__global__ void matmul_kernel(float *A, float* B, float *C, int n)
{
    int i, j, k;
    float c;

    i = blockIdx.x;
    for(i=i; i < n; i += gridDim.x){
        j = threadIdx.x;
        c = 0.0;
        for(k = 0; k < n; k++)
            c += A[i*n + k]*B[k*n + j];
        C[i*n + j] = c;
    }
}

dim3 grid(1,1,1);
dim3 block(128,1,1);
n = 128;
matmul_kernel<<<grid, block>>>(A, B, C, n);

我使用最简单的矩阵乘法作为例子。在上面的CUDA实现中,我将i循环迭代映射到每个线程块中的块索引和j循环到线程索引。线程块和网格都是一维的。

请不要关注此实施的效果。我知道它效率不高,因为我只是将它用于实验目的。

在此实现中,由于我在每个块中分配了128个线程,因此j循环可以完全并行化。但我只为i循环分配了1个块,因此它将循环n次。下图显示了k=0时的执行状态。在此状态下,128个线程访问A的第一个元素和B的128个第一行元素。我在使用Kepler 40架构的Quadro K6000上执行此CUDA代码,然后打开了L1缓存。由于合并了对B的128次访问,因此加载次数为128*4/128 = 4(第一个128是128个元素,第二个128是L1缓存行大小的字节数,4是字节数浮动型)。对于A的128次访问,由于它们访问相同的元素,因此1个缓存行加载应该足够。因此全局负载的数量为4+1=5。但这只是k=0时的负载数量。 k将循环128次,i也将循环128次,因此加载总数为5*128*128=81920。但是,配置文件的全局负载为131072。该值等于(4+4)*128*128A k=0的{​​{1}}的加载次数似乎是4而不是1.任何人都可以解释为什么分析值与我的预期值不匹配?

https://gist.github.com/kinlane/922855

1 个答案:

答案 0 :(得分:2)

你错过了一个小点。全局内存访问仅针对warp 中的线程进行合并(请参阅programming guide)。在你的情况下,有4个经线。对于A的元素,每个都需要一个内存事务。