CUDA:线程和数组分配

hqt*_*hqt 1 cuda

我已多次阅读有关CUDA线程/块和数组的内容,但仍然不明白点:CUDA如何以及何时开始为内核函数运行多线程.当主机调用内核函数或内核函数时.

例如,我有这个例子,它只是简单地转置一个数组.(因此,它只是将值从此数组复制到另一个数组).

__global__
void transpose(float* in, float* out, uint width) {
    uint tx = blockIdx.x * blockDim.x + threadIdx.x;
    uint ty = blockIdx.y * blockDim.y + threadIdx.y;
    out[tx * width + ty] = in[ty * width + tx];
}

int main(int args, char** vargs) {
    /*const int HEIGHT = 1024;
    const int WIDTH = 1024;
    const int SIZE = WIDTH * HEIGHT * sizeof(float);
    dim3 bDim(16, 16);
    dim3 gDim(WIDTH / bDim.x, HEIGHT / bDim.y);
    float* M = (float*)malloc(SIZE);
    for (int i = 0; i < HEIGHT * WIDTH; i++) { M[i] = i; }
    float* Md = NULL;
    cudaMalloc((void**)&Md, SIZE);
    cudaMemcpy(Md,M, SIZE, cudaMemcpyHostToDevice);
    float* Bd = NULL;
    cudaMalloc((void**)&Bd, SIZE); */
    transpose<<<gDim, bDim>>>(Md, Bd, WIDTH);   // CALLING FUNCTION TRANSPOSE
    cudaMemcpy(M,Bd, SIZE, cudaMemcpyDeviceToHost);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

(我已经评论了所有不重要的行,只是让行调用函数转置)

除了线路调用功能,我已经理解了函数main中的所有行tranpose.当我说:当我们调用函数时transpose<<<gDim, bDim>>>(Md, Bd, WIDTH),CUDA会自动将数组的每个元素分配到一个线程(和块)中,当我们调用"一次"转换时,CUDA会gDim * bDimgDim * bDim线程上运行时间.

这一点让我感到非常沮丧,因为它不喜欢java中的多线程,当我使用:(请告诉我.

谢谢 :)

Rog*_*ahl 5

你的理解本质上是正确的.

transpose不是函数,而是CUDA内核.当您调用常规函数时,它只运行一次.但是当你一次启动内核时,CUDA会自动多次在内核中运行代码.CUDA通过启动许多线程来做到这一点.每个线程一次运行内核中的代码.tripple括号(<<< >>>)内的数字称为内核执行配置.它确定CUDA将启动多少个线程并指定线程之间的某些关系.

将通过将网格中的所有值与三个括号内的块尺寸相乘来计算将要启动的线程数.例如,在您的示例中,线程数将为1,048,576(16*16*64*64).

每个线程都可以读取一些变量来找出它是哪个线程.这些是内核顶层的结构blockIdxthreadIdx结构.值反映了内核执行配置中的值.所以,如果你用16×16(第一网格配置中运行你的内核dim3在三重括号,你会得到线程,当他们每个阅读xy中值blockIdx结构,将得到的所有可能的组合xy介于0和15.

因此,如您所见,CUDA对数组元素或任何其他特定于您的内核的数据结构一无所知.它只处理线程,线程索引和块索引.然后,您可以使用这些索引来确定给定线程应该执行的操作(特别是应该处理的应用程序特定数据中的哪些值).