线程索引作为 CUDA 中的内存位置索引

Thread index as an memory location index in CUDA

根据定义,线程是进程内的执行路径。 但是在内核的实现过程中,会生成 thread_id 或 global_index 来访问分配的内存位置。例如,在下面的矩阵乘法代码中,生成 ROWCOL 以顺序访问矩阵 A 和 B。 我在这里的疑问是,生成的索引不是指向线程(根据定义),而是用于访问内存中数据的位置,那么为什么我们将其称为线程索引或全局线程索引并且为什么不是内存索引或其他东西?

__global__ void matrixMultiplicationKernel(float* A, float* B, float* C, int N) {

    int ROW = blockIdx.y*blockDim.y+threadIdx.y;
    int COL = blockIdx.x*blockDim.x+threadIdx.x;

    float tmpSum = 0;

    if (ROW < N && COL < N) {
        // each thread computes one element of the block sub-matrix
        for (int i = 0; i < N; i++) {
            tmpSum += A[ROW * N + i] * B[i * N + COL];
        }
    }
    C[ROW * N + COL] = tmpSum;
}

这个问题似乎主要是关于语义的,所以让我们从 Wikipedia

开始

.... a thread of execution is the smallest sequence of programmed instructions that can be managed independently by a scheduler ....

这几乎准确描述了 CUDA 中的线程是什么 -- 内核是指令序列,调度器是 GPU 上每个流式多处理器中的 warp/thread 调度器。

您问题中的代码正在计算内核启动中线程的唯一 ID,因为它是在 CUDA programming/execution 模型中抽象出来的。它与内存布局没有内在关系,仅与内核启动中的唯一 ID 相关。它被用来确保每个并行操作在不同的内存位置上执行的事实是编程技术,仅此而已。

Thread ID 对我来说似乎是一个合乎逻辑的绰号,但是当 Miles Davis 被问及他的乐队在 1970 年的怀特岛音乐节上演奏的果酱的名字时,用他的话说:“随便你怎么叫” .