首页 > 代码库 > CUDA C编程入门-硬件实现

CUDA C编程入门-硬件实现

  NVIDIA GPU架构是建立在一个可扩展的多线程流处理器(SMs)阵列之上的。当一个在主机CPU的CUDA程序调用一个核函数时,网格的blocks分配给运行容量空闲的多核处理器计算。线程块的线程同时在多核处理器上执行,多个线程块能同时在一个多核处理器上执行。当线程块结束时,新的线程块会加载到空出的多核处理器上。

  一个多核处理器被设计成能同时执行数以百计的线程。为了管理这样大容量的线程,GPU使用一个在SIMT架构描述的叫SIMT(单个指令,多个线程)的独特架构。在单个线程中,指令是流水的去利用指令级别的并行,和通过同时发生的硬件多线程(细节在硬件多线程)的线程级别并行一样。不像CPU核心,指令被按序发射,没有分支预测和推测执行。

  SIMT架构和硬件多线程描述流处理器是对所有设备的共同的架构特性。计算能力为1.x、2.x、3.x和5.0章节分别地提供计算能力为1.x、2.x、3.x和5.0的细节。

  NVIDIA GPU架构使用小端表示。

4.1 SIMT架构

  多核处理器以叫做warps的32个并行线程为一组来创建、管理、安排和执行线程。组成warps的单个线程在程序的同一的程序地址开始,但是,都拥有自己的指令地址计数器和寄存器状态,因此,可以自由地分支和独立地执行。术语warp源于weaving,第一个并行的技术。一个half-warp不是warp的前半个就是后半个。一个四分之一的warp不是第一、第二、第三和第四的四分之一warp。

  当给定一个多核处理器一个或者多个线程块去执行,会把线程块划分成warps,每个warp通过一个warp调度程序安排执行。一个线程块划分成warp的方式总是相同的,每个warp包含连续的线程,递增的线程ID,第一个warp含有ID为0的线程。线程层次这章节描述在线程块的线程ID怎样与线程索引相关。

  一个warp在一个时刻执行一个指令,当一个warp的32个线程执行的路径一致时,此时实现全部的效率。如果warp的线程分出依赖数据的条件分支,warp执行这个分支路径,线程不会在其它分支执行,当所有的分支完成后,线程集中回到相同的执行路径。分支只会在一个warp内出现。不同的warp独立地执行,不管它们是执行在相同的或者不同的代码路径上。

  SIMT架构类似于SIMD向量组织,单个指令控制多个处理中的元素。SIMD向量组织的一个关键的区别是会提供SIMD宽度给软件。而SIMT指令指定单个线程的执行和分支行为。与SIMD相比,SIMT是程序员能写出独立的具体数量的线程的线程级别的并行代码和线程相应的数据并行代码。为了正确的目的,程序员能基本上忽视SIMT的行为,然而,注意在warp的线程很少有分支的代码会提升实际执行的性能。实际上,这相当于传统代码中的cache lines的角色:为了正确性,cache line大小能安全的忽视,而为了最佳性能,必须在代码结构中考虑到。向量组织,另一方面,要求软件合并加载进向量,并手工地管理分支。

  注意:

  warp的线程,在warp当前执行路径的线程叫活跃线程,而不在当前执行路径的叫不活跃线程。线程能不活跃是因为warp中的其他的线程早就退出,或者因为它们在与warp当前执行的路径的不同的执行路径,或者是因为它们是线程数不是warp大小的倍数的线程块的最后的线程。

  如果一个被warp中多个线程执行写数据到全局或者共享内存的同一位置单元的非原子指令,系列化的写的引起该单元变化的数目依赖于设备的计算能力,且那个线程执行最后的写是未定义的。

  如果一个被warp中多个线程执行读、修改和写数据到全局内存的同一单元的原子指令,每个读/修改、写那个单元,它们所有都被系列化,但它们的执行顺序是未定义的。

 

4.2 硬件多线程

  在warp整个生命周期里,每个被多核处理器执行的warp的上下文(程序计数器、寄存器等)依靠在芯片上。因此,从一个执行的上下文转换到另一个没有代价,在整个指令发射时间,warp调度程序选择一个有线程准备执行下一个指令的warp,发射这些线程的指令。

  尤其地,每个处理器有一系列被warp划分的32位寄存器,一个被线程块划分的并行的数据缓存或者共享内存。

  对一个给定的核函数,可以在处理器上驻留和处理的线程块和warp的数量取决于在处理器可用的寄存器的数量和被核函数使用的共享内存。这里也有在一个处理器上驻留的线程块的最大数量和驻留的warps最大数量。这些同样限制于寄存器的数量和处理器上可用的共享内存,是附录F给定的设备计算能力的函数。如果在每个处理器上没有足够的可用的寄存器或者共享内存去处理至少一个线程块,核函数加载将失败。

  一个线程块的warp的数量如下:

  • ceil(T/Wsize,1)
  • T是每个线程块线程的数量。
  • Wsize是warp大小,等于32。
  • ceil(x,y)等于x去最靠近y倍数的整数。

  寄存器的数量和一个线程块可分配的共享内存的总数是在CUDA软件开发包的CUDA占用计算器记录。