C++ CUDA线程ID

C++ CUDA线程ID,c++,cuda,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

我是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;
}
\uuuu全局\uuuuu无效gpuMM(浮点*A、浮点*B、浮点*C、整数N)
{
//NxN矩阵C=A*B的矩阵乘法
//每个线程计算一个C元素
int col=blockIdx.y*blockDim.y+threadIdx.y;
int row=blockIdx.x*blockDim.x+threadIdx.x;
浮点数和=0.f;
对于(int n=0;n
CUDA并不意味着任何内存存储结构。可以说CUDA C是矩阵存储的主要行,但这是由于C,而不是CUDA。(CUDA Fortran将是主要列。)线程索引维度是任意的。它们并不意味着内存中的数据存储顺序

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

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

因为它将允许读取
B[]
和写入
C[]
合并

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


这特别容易尝试,因为您的内核代码暗示了平方矩阵。

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

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

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

因为它将允许读取
B[]
和写入
C[]
合并

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


这特别容易尝试,因为您的内核代码暗示了平方矩阵。

行主顺序和CUDA线程索引应该以何种方式影响计算精度?因为顺序不同。例如,当我们考虑矩阵的第一行时,它是像[0 ]〔0〕、〔0〕〔1〕、〔0〕〔2〕…〔0〕〕,而在CUDA中则是(0,0)(1 0)(2,0)……因此,你担心的是正确性,而不是准确性。正如@RobertCrovella所回答的,您可以通过行主排序获得正确的结果。我认为行主键(例如C++)和列主键(Fortran)之间的结果精度也不会有差异,因为操作的顺序是相同的(以不同的顺序求和编号原则上可能会产生略有不同的结果)。行主排序和CUDA线程索引应以何种方式影响计算的准确性?因为排序不同。例如,当我们考虑矩阵的第一行时,它是像[0 ]〔0〕、〔0〕〔1〕、〔0〕〔2〕…〔0〕〕,而在CUDA中则是(0,0)(1 0)(2,0)……因此,你担心的是正确性,而不是准确性。正如@RobertCrovella所回答的,您可以通过行主排序获得正确的结果。我认为行主键(例如C++)和列主键(Fortran)之间的结果精度也不会有差异,因为操作的顺序是相同的(以不同的顺序求和编号原则上可能会产生略有不同的结果)。
int row = blockIdx.y*blockDim.y + threadIdx.y;
int col = blockIdx.x*blockDim.x + threadIdx.x;