暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Cuda编程(二):GPU架构基础

Qiang的杂谈 2019-11-13
1281

并行计算指令

图1 并行计算指令分类[1]

SISD,Single Instruction Single Data,同时只能处理一条指令并处理一个数据的串行指令,绝大部分CPU都不支持SISD。

SIMD,Single Instruction Multiple Data,一条指令同时处理多条数据的指令,Nvidia的GPU以及AMD的SIMD都遵循这样的设计。

MIMD,Multiple Instructions Multiple Data,几乎所有的GPU和CPU都支持该指令。GPU由多个SM(Streaming Multiprocessor)单元组成,多个SM集成工作的方式也属于MIMD。

MISD,Multiple Instructions Single Data,主要用于高可靠性系统(航空、航天及军事领域),数据被多个处理器处理以保证容错性。

如图1所示,Instruction Pool负责指令的发射,Data Pool负责数据操作:数据访问、交换,PU,Processing Unit [2]。


GPU体系架构

GPU硬件设计

SP,Streaming Processor,Cuda Core,最终的指令和任务都是运行在SP上的。

SM,Streaming MultiProcessors,是SP以及其他资源(wrap scheduler,registers,shared memory)的总和。

在不同GPU体系架构中,SM中包含的SP的数量不同,这也直接影响的GPU的性能。


Fermi架构

Fermi架构GPU包含512个Cuda cores(SP),这512个core被分为16个SM(Streaming Multiprocessors),每个SM包含32个core。最大支持6GB的GDDR5内存空间。每个SM包含32个core,每个Cuda core包含一个整型处理单元和浮点处理单元(FPU).[3]

图2 Fermi架构

如图3所示,Fermi的SM的架构:

图3 Fermi SM架构

Kepler/HyperQ体系架构

制造工艺(40nm v.s. 28nm)、cache大小、SM包含的cuda core的个数、physical die的大小、功耗、精简的流水线指令等(图4所示)。

图4 Fermi v.s. Kepler物理比较


Kepler架构如图5所示:

图5 Kepler体系架构


Kepler SMX架构

- 从内存角度,Kepler架构增加了Read Only Data Cache

从并行化角度,Kepler动态并行,允许一个kernel里启动另一个kernel,较少了GPU和CPU之间的通信

- 增加了DP,在Cuda上使用Double

- Hyper-Q技术

图6 Kepler SMX架构

Hyper-Q技术允许主机与GPU之间提供32个硬件工作队列,以减少任务在队列中阻塞的可能性,保证在GPU上可以有更多的并发执行,更大程度上提升GPU性能。如图7所示,Fermi下单队列与Hyper-Q技术间的对比。

图7 Fermi v.s Kepler Hyper-Q工作队列


Cuda编程模型

图8 Cuda编程模型


软件模型:Thread/Block/Grid/Kernel

Thread是Cuda编程里的最基本执行单元,多个threads组成一个block,多个blocks组成grid。Block中的threads可以是一维、二维、三维的,grid中的blocks也可以是一维、二维、三维的。Block可以通过blockIdx索引,block的维度可以用blockDim访问,同一个Block中的Thread通信可以通过共享内存的方式,如图9所示。

图9 Thread、Block和Grid之间的关系

Wrap是GPU调度的最小单位,同一个wrap的不同线程以不同的数据资源执行相同的指令就是SIMT(Single Instruction Multiple Threads),可以理解SIMT是SIMD的线程版,不同的是[5]:

  • PU处理的向量大小由软件定义,即线程块的大小

  • 每个thread拥有自己的instruction address counter

  • 每个thread拥有自己的状态寄存器

  • 每个thread可以有自己独立的执行路径

一个block只由一个sm调度,block内部相应的线程信息描述在编程时进行说明,执行时的调度由sm的wrap scheduler负责,一个block在指定相应的sm后就会一直驻留在该sm中,一个sm可以享有多个blocks,调度时需顺序执行。相同wrap内的threads在调度时会有竞态发生,但不同wrap之间是可以完全并行的。GPU对每个thread都分配了独立的寄存器,无需保存/恢复上下文。


如图9所示的Grid,编写一个被线程网格中所有线程执行的函数称为kernel。调用kernel时需要特定的语法:<<<grid, block>>>来指定线程的组织层次。


修饰符host和device

Cuda编程与C语言相似,不同的是需要在kernel函数前声明修饰符,以保证该函数运行的上下文(CPU侧或GPU侧)

  • __device__,设备端调用并在设备端执行

  • __host__,主机端函数,仅能够被CPU调用

  • __global__,可以被GPU调用,也可以调用__device__声明的函数


[1] http://www.thephysicsmill.com/2014/07/27/parallel-computing-primer/

[2] http://www.thephysicsmill.com/2014/07/27/parallel-computing-primer/

[3] https://www.3dgep.com/cuda-thread-execution-model/#GPU_Architecture

[4] http://blog.cuvilib.com/2014/11/12/cuda-differences-bw-architectures-

and-compute-capability/

[5] https://blog.csdn.net/yu132563/article/details/60881130

文章转载自Qiang的杂谈,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论