参考资料
技术美术百人计划】图形 2.7.2 GPU硬件架构概述
英伟达GPU架构演进近十年,从费米到安培
cpu的基本结构及其工作原理
架构对比
从上图可以看出,CPU架构可以粗略的分为控制单元,存储单元和运算单元,其中数据和指令被放在存储单元中,控制单元从存储单元读取数据和指令并向对应部件发出控制信号,运算单元依据控制信号进行一系列的算数运算和逻辑运算。
对比CPU和GPU的硬件架构可以看出:
在存储方面:CPU发展出多级缓存结构,其存储部分也占用了大量的晶体管资源。而GPU虽然也有多级缓存,如全局内存,本地内存,共享内存等,但更多的晶体管还是用于计算,这使得GPU可以同时执行上千个线程。
在计算方面:有一点值得注意:在GPU的图中可以看出,每一行有多个Core,却只有一个Control,这代表着多个Core同一时刻只能执行同样的指令,因此不能简单的将一个cuda core等同于一个cpu核心。
在控制方面:因为CPU需要很强的通用性来处理各种不同的数据类型,在逻辑判断又会引入大量的分支跳转和中断的处理,这使得CPU的内部结构异常复杂,需要集成众多的指令集。而GPU面对的则是类型高度统一的、相互无依赖的大规模数据和不需要被打断的纯净的计算环境,因此更加简洁。
总体上看,因为GPU的特殊构造,只有 计算密集 与 数据并行 的程序适合使用GPU:
- 计算密集:数值计算 的比例要远大于 内存操作,因此内存访问的延时可以被计算掩盖,从而对Cache的需求相对CPU没那么大。
- 数据并行: 大任务可以拆解为执行相同指令的小任务,因此对复杂流程控制的需求较低。
费米架构
Fermi是Nvidia在2010年发布的架构,引入了很多今天也仍然不过时的概念。
从上往下看:
Host Interface与GigaThread Engine
位于最外层,表示是GPU与CPU交互的层,分别接收控制信号和数据
GPU通过Host Interface读取CPU指令,GigaThread Engine将特定的数据从Host Memory中拷贝到内部的Framebuffer中。随后GigaThread Engine创建并分发多个Thread Blocks到多个SM上。多个SM彼此独立,并独立调度各自的多个Thread Wraps到SM内的CUDA Cores和其他执行单元上执行。
Raster engine是光栅处理引擎,可以不管
GPC
GPC是Graphics Processing Cluster图形处理集群的缩写,属于GPU的次级单位,上图有四个GPC。
SM(Streaming Multiprocessors 流式多处理器)
上图存在16个SMs,每个SM带32个Cuda Cores,一共512个Cuda Cores. 这些数量不是固定的,和具体的架构和型号相关。
CUDA核心
从上图可知,SM内有32个CUDA Cores,每个CUDA Core含有一个Integer arithmetic logic unit 和一个Floating point unit(FPU),并且提供了对于单精度(32位)和双精度(64位)浮点数的FMA指令。
注:
ALU即算数逻辑单元,属于计算器部分,用于计算加减乘除的数学运算和与或非的逻辑运算
精度方面一般单精度的就足够了
LD/ST单元
SM内还有16个LD/ST单元,也就是Load/Store单元,支持16个线程一起从Cache/DRAM存取数据。
SFU(Special Function Unit)
4个,用于计算sin/cos,log,rsqrt这类特殊指令,由Dispatch Unit解耦,确定使用SFU还是别的计算单元
Warp
在之前的SM概览图以及上图里,可以注意到SM内有两个Warp Scheduler和两个Dispatch Unit. 这意味着,同一时刻,会并发运行两个warp,每个warp会被分发到一个Cuda Core Group(16个CUDA Core), 或者16个load/store单元,或者4个SFU上去真正执行,且每次分发只执行 一条 指令,而Warp Scheduler维护了多个(比如几十个)的Warp状态(可能有多个cuda程序并行执行,这时由warp scheduler负责切换)。
这里引入了一个核心的约束,任意时刻,一个Warp里的Thread都在执行同样的指令,对于程序员来说,观测不到一个warp里不同thread的不同执行情况。
那些情况不适合GPU加速/加速效果差
cuda加速流程可以分为三个步骤:数据载入(host到device),计算(通过一系列的核函数),结果导出(device到host),在出现以下情况时需要考虑是否有必要镜像cuda加速:
1.载入的数据量过小或需要反复传输数据
2.核函数内使用大量的逻辑判断或循环操作
3.多个线程访问同一个锁
4.大批量处理小数据(例如,做一万个22矩阵的点乘计算就不如做单个200200矩阵的点乘计算,因此对小矩阵的一般建议拼接后再处理)