了解CUDA网格尺寸,块尺寸和线程组织(简单说明)

时间:2010-03-06 11:08:52

标签: cuda nvidia

如何组织线程执行GPU?

2 个答案:

答案 0 :(得分:274)

硬件

例如,如果GPU设备有4个多处理单元,并且它们每个可以运行768个线程:那么在给定时刻不会有超过4 * 768个线程并行运行(如果您计划更多线程,它们将等待轮到他们。)

软件

线程按块组织。块由多处理单元执行。 可以使用1维度(x),2D维度(x,y)或3Dim索引(x,y,z)来识别(索引)块的线程,但是在任何情况下x y z <= 768为我们的示例(其他限制适用于x,y,z,请参阅指南和您的设备功能)。

显然,如果您需要超过4 * 768个线程,则需要超过4个块。 块也可以被索引为1D,2D或3D。有一个等待进入的块队列 GPU(因为在我们的例子中,GPU有4个多处理器,只有4个块 同时执行。)

现在是一个简单的案例:处理512x512图像

假设我们想要一个线程处理一个像素(i,j)。

我们可以使用每个64个线程的块。然后我们需要512 * 512/64 = 4096个块 (所以要有512x512个线程= 4096 * 64)

组织(使图像索引更容易)通常是具有blockDim = 8 x 8(每个块64个线程)的2D块中的线程。我更喜欢称它为threadsPerBlock。

dim3 threadsPerBlock(8, 8);  // 64 threads

和2D gridDim = 64 x 64块(需要4096块)。我更喜欢称它为numBlocks。

dim3 numBlocks(imageWidth/threadsPerBlock.x,  /* for instance 512/8 = 64*/
              imageHeight/threadsPerBlock.y); 

内核启动如下:

myKernel <<<numBlocks,threadsPerBlock>>>( /* params for the kernel function */ );       

最后:会出现类似“4096个块的队列”的情况,其中一个块正在等待分配GPU的多个处理器之一以执行其64个线程。

在内核中,线程处理的像素(i,j)以这种方式计算:

uint i = (blockIdx.x * blockDim.x) + threadIdx.x;
uint j = (blockIdx.y * blockDim.y) + threadIdx.y;

答案 1 :(得分:6)

假设9800GT GPU: 14个多处理器,每个都有8个线程处理器,warpsize是32,这意味着每个线程处理器最多可处理32个线程。 14 * 8 * 32 = 3584是实际当前螺纹的最大数量。

如果你用超过3584个线程执行这个内核(比如说4000个线程,你定义块和网格的方式并不重要.gpu会像对待它们一样对待它们):

func1();
__syncthreads();
func2();
__syncthreads();

然后这两个函数的执行顺序如下:

1.func1是针对前3584个线程执行的

2.func2是针对前3584个线程执行的

对剩余的线程执行3.func1

4.func2执行剩余的线程