CUDA线程ID

时间:2013-12-05 06:28:02

标签: c++ cuda

我是CUDA编程的新手,我遇到了以下问题。

如果我使用以下代码执行矩阵乘法,由于CUDA使用笛卡尔索引进行线程索引,而C / C ++使用矩阵的行主索引,是否会影响计算的准确性?

__global__ void gpuMM(float *A, float *B, float *C, int N)
{
    // Matrix multiplication for NxN matrices C=A*B
    // Each thread computes a single element of C

    int col = blockIdx.y*blockDim.y + threadIdx.y;
    int row = blockIdx.x*blockDim.x + threadIdx.x;

    float sum = 0.f;
    for (int n = 0; n < N; ++n)
        sum += A[row*N+n]*B[n*N+col];

    C[row*N+col] = sum;
}

1 个答案:

答案 0 :(得分:4)

CUDA并不意味着任何内存存储结构。你可以说CUDA C是矩阵存储的行专业,但这是由于C而不是CUDA。 (CUDA Fortran将是列专业。)线程索引维度是任意的。它们并不意味着内存中的数据存储顺序。

当您编写代码时,会出现对内存中数据存储顺序的影响。从正确性的角度来看,如果我们根据x线程维度或y线程维度分配行索引并不重要。您可以使用任一方法(基于x的行,或基于y的行)为此矩阵乘法示例编写正确的代码。

然而,从合并的角度来看,我们通常希望相邻的执行线程读取或写入内存中的相邻单元。相邻线程(用于执行)通常首先分组为x。因此,这是优选的(对于您的内核代码):

int row = blockIdx.y*blockDim.y + threadIdx.y;
int col = blockIdx.x*blockDim.x + threadIdx.x;

因为它允许读取B[]和写C[]来合并。

这很容易向自己证明。尝试两种方式,并测量内核的执行时间。结果是正确的(与使用基于主机的矩阵乘法产生的结果相匹配)无论哪种方式,但是一个公式的运行速度明显快于另一个公式。

这很容易尝试,因为你的内核代码意味着方形矩阵。