CUDA:线程和数组分配

CUDA:线程和数组分配,cuda,Cuda,关于CUDA线程/块和数组,我已经读了很多遍了,但仍然不理解其中的要点:CUDA如何以及何时开始为内核函数运行多线程。当主机调用内核函数时,或者在内核函数内部 例如,我有这个例子,它只是简单地转置一个数组。(所以,它只是将值从这个数组复制到另一个数组) \u全局__ 无效转置(浮动*入、浮动*出、单位宽度){ uint tx=块IDX.x*块尺寸x+线程IDX.x; uint ty=blockIdx.y*blockDim.y+threadIdx.y; out[tx*宽度+ty]=in[ty*宽度

关于CUDA线程/块和数组,我已经读了很多遍了,但仍然不理解其中的要点:CUDA如何以及何时开始为内核函数运行多线程。当主机调用内核函数时,或者在内核函数内部

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

\u全局__
无效转置(浮动*入、浮动*出、单位宽度){
uint tx=块IDX.x*块尺寸x+线程IDX.x;
uint ty=blockIdx.y*blockDim.y+threadIdx.y;
out[tx*宽度+ty]=in[ty*宽度+tx];
}
int main(int参数,字符**vargs){
/*常数int高度=1024;
常数整型宽度=1024;
常量int SIZE=宽度*高度*大小of(浮点);
dim3-bDim(16,16);
dim3 gDim(宽度/bDim.x,高度/bDim.y);
浮动*M=(浮动*)malloc(大小);
对于(inti=0;i
(我已经注释了所有不重要的行,只使用了行调用函数transpose)

除了调用函数
transpose
的行之外,我已经理解了函数main中的所有行。当我说:当我们调用函数
transpose(Md,Bd,WIDTH)
时,CUDA会自动将数组的每个元素分配到一个线程(和块),当我们调用“one time”transpose时,CUDA会在
gDim*bDim
线程上运行
times transpose

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


谢谢:)

你的理解基本上是正确的

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

将要启动的线程数是通过将三个方括号内栅格和块尺寸中的所有值相乘来计算的。例如,在您的示例中,线程数将为1048576(16*16*64*64)

每个线程都可以读取一些变量来找出它是哪个线程。这些是位于内核顶部的
blockIdx
threadIdx
结构。这些值反映了内核执行配置中的值。因此,如果您使用16 x 16的网格配置运行内核(三个括号中的第一个
dim3
),您将获得线程,当它们各自读取
blockIdx
结构中的
x
y
值时,将获得
x
y
的所有可能组合,这些值介于0和15之间


因此,正如您所看到的,CUDA不知道任何特定于内核的数组元素或任何其他数据结构。它只处理线程、线程索引和块索引。然后您可以使用这些索引来确定给定线程应该做什么(特别是,它应该处理特定于应用程序的数据中的哪些值)你的理解基本上是正确的

transpose
不是一个函数,而是一个CUDA内核。当你调用一个常规函数时,它只运行一次。但是当你一次启动一个内核时,CUDA会自动在内核中运行多次代码。CUDA通过启动多个线程来实现这一点。每个线程在内核中运行一次代码。三重b中的数字rackets(
)称为内核执行配置。它确定CUDA将启动多少线程,并指定线程之间的一些关系

将要启动的线程数是通过将三个括号内的网格和块维度中的所有值相乘来计算的。例如,在您的示例中,线程数将为1048576(16*16*64*64)

每个线程都可以读取一些变量以确定它是哪个线程。这些变量是位于内核顶部的
blockIdx
threadIdx
结构。这些值反映内核执行配置中的值。因此,如果您以16 x 16的网格配置运行内核(三个括号中的第一个
dim3
,您将获得线程,当它们各自读取
blockIdx
结构中的
x
y
值时,将获得
x
y
在0和15之间的所有可能组合

因此,正如您所看到的,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;
}