第二天:CUDA编程之thread/block/grid概念

本文详细介绍了CUDA C++如何扩展标准C++,用于实现高效的并行计算。内容涵盖kernel函数、thread ID、thread索引与block的关系,以及thread、block和grid的组织结构。在示例中展示了如何处理向量和矩阵的并行加法操作。文章强调了thread、block和grid作为软件概念,并指出它们的独立执行和同步特性。最后,提到了共享内存在多线程协作中的作用。
摘要由CSDN通过智能技术生成

一、CUDA C++对标准C++的扩展

1.允许用户定义C++函数,并用__global__前缀修饰,并且这类函数有个专用名字:kernel

2.调用kennel的时候需要在kernel名字和参数之间加<<<....>>>修饰,用来限定并行执行该kernel的thread个数。

3.每一个执行该kernel的thread都有一个特定的thread ID,程序中可以通过CUDA C++内建变量threadIdx来获取。

下面举个例子:两个(1,N)向量(向量A和向量B)相加得到向量C的CUDA C++实现。以上知识点在下面这段程序示例中都有体现:

 

两个(1,N)向量相加,涉及N次加法,这里起N个thread,每个thread执行一个加法,那么N个thread并行执行一次加法,就可以得到C的结果。

kernel中的i,叫作thread index,与thread id有什么关系?——答案见下一节。

 

二、Thread层级

实际上,threadIdx是一个3-component vector(就是一个三维坐标系向量),所以,一个thread可以使用一维/二维/三维形式的thread索引。

为什么thread要用这样三种索引方式呢?——因为构成一个block的threads有one dimensional, two-dimensional, or three-dimensional这三种形式。也叫作xxx-dimensional thread block.

相应的,This provides a natural way to invoke computation across the elements in a domain such as a vector, matrix, or volume.——也就是说,进行计算的数据维度与block中的threads的维度保持一致。

 

所以,thread index和thread id之间的关系是如何的呢?

首先,thread id是通过thread index计算得到的。

对于one-dimensional block, they are the same;

对于two-dimensional block of size (Dx , Dy),the thread ID of a thread of index (x, y) is (x + y*Dx)

对于three-dimensional block of size (Dx , Dy , Dz), the thread ID of a thread of index (x, y, z) is (x + y*Dx + z*Dx*Dy).

 

下面举个例子:两个(N,N)矩阵(矩阵A和矩阵B)相加得到矩阵C的CUDA C++实现。以上知识点在下面这段程序示例中都有体现:

 

两个(N,N)矩阵相加,涉及N*N次加法,这里起N*N个thread,每个thread执行一个加法,那么N*N个thread并行执行一次加法,就可以得到C的结果。运行其中一个加法的thread id是通过执行该加法的thread index计算得到的。

<<<1,N*N>>>指定了执行该thread的个数。

 

 

三、Grid和Block

到目前为止,thread的组织结构已经很清楚了,那block又是如何被组织起来的呢?

下面展示一个two-dimensional threads of block:

 

同thread一样,Blocks are organized into a one-dimensional, two-dimensional, or three-dimensional grid of thread blocks as illustrated by Figure 4. The number of thread blocks in a grid is usually dictated(指示) by the size of the data being processed, which typically exceeds the number of processors in the system.

 

通过Figure 4可以知道:站在组织结构上来说,grid > block > thread。

并且,从上面这段英文描述中可以看出,其实grid/block/thread都是软件的概念,而非硬件概念,这点要注意。

 

你写的kernel就决定了the shape of thread block,并且一个kernel可以被多个相同shape的thread blocks同时执行。此时,总的threads个数 = block的个数 * 每个block包含的threads个数。

 

即使thread/block/grid都是软件概念,但是每个block的thread个数仍然是有限的,因为一个block的所有threads需要在同一个处理器核心上运行,并且共享该处理器核心有限的memory。所以,当前技术基础的GPUs, a thread block may contain up to 1024 threads。

所以,问题来了,如果上述两个N维矩阵相加,如果N足够大,导致thread的个数超过了一个block的限制,那么这时候必然会使用多个block来完成计算,那这个程序又该如何实现呢?——Figure 4就是这个程序的图示说明。

 

程序说明:

  1. 每个block包含256(16*16)个thread,two-dimensional结构(每个矩阵元素就是一个thread)。
  2. 每个grid包含(N/16)*(N/16)个block,two-dimensional结构(每个矩阵元素就是一个block)。

对于这个过程:我个人的理解就是:block划分相当于就是对grid所包含的所有thread组成的二维矩阵分别进行x方向和y方向等分切片,切片后得到的每一小块就是一个threads of block。

 

四、简单总结

   1.<<<...>>>中的参数包括两个:

       每个grid包含的block个数,类型可以是int或者dim3

       每个block包含的thread个数,类型可以是int或者dim3

       注意:a.这两个参数其实也就限定了执行该kernel的thread个数

                  b.Two-dimensional blocks or grids can be specified as in the example above(其实就是将三维向量的z坐标写为1即可)。

    2. 同threadIdx一样,blockIdx 是一个3-component vector(就是一个三维坐标系向量),所以,一个block可以使用一维/二维/三维形式的block索引。

    3. block的维度可以通过一个built-in变量blockDim获取。

 

    4. Thread blocks are required to execute independently: It must be possible to execute them in any order, in parallel or in series. This independence requirement allows thread blocks to be scheduled in any order across any number of cores as illustrated by Figure 3, enabling programmers to write code that scales with the number of cores.

     5. Threads within a block can cooperate by sharing data through some shared memory and by synchronizing their execution to coordinate memory accesses.

         对于4、5点,用一句大白话解释:block独立执行,不依赖与其他block,也不需要和其他block同步;thread执行可能要依赖同block下的其他thread执行情况,依赖的方式包括:数据同步(共享)和执行同步。

 

      当然,数据同步/执行同步都是通过共享内存来实现的,但是出于性能考虑,共享内存必须是低延迟访问内存,L1 cache就是最佳选择。下一篇文件分析CUDA内存同步相关知识。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

denglin12315

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值