揭秘英伟达 GPU 架构演进近十年,从费米到安培

作者:tomoyazhang,腾讯 PCG 后台开发工程师
,腾讯 PCG 后台开发工程师

【揭秘英伟达 GPU 架构演进近十年,从费米到安培】随着软件从 1.0 进化到 2.0,也即从图灵机演进到类深度学习算法 。计算用的硬件也在加速从 CPU 到 GPU 等迁移 。本文试图整理从英伟达 2010 年开始,到 2020 年这十年间的架构演进历史 。
CPU and GPU我们先对 GPU 有一个直观的认识,如下图:
揭秘英伟达 GPU 架构演进近十年,从费米到安培

文章插图
 
众所周知,由于存储器的发展慢于处理器,在 CPU 上发展出了多级高速缓存的结构,如上面左图所示 。而在 GPU 中,也存在类似的多级高速缓存结构 。只是相比 CPU,GPU 将更多的晶体管用于数值计算,而不是缓存和流控(Flow Control) 。这源于两者不同的设计目标,CPU 的设计目标是并行执行几十个线程,而 GPU 的目标是要并行执行几千个线程 。
可以在上面右图看到,GPU 的 Core 数量要远远多余 CPU,但是有得必有失,可以看到 GPU 的 Cache 和 Control 要远远少于 CPU,这使得 GPU 的单 Core 的自由度要远远低于 CPU,会受到诸多限制,而这个限制最终会由程序员承担 。这些限制也使得 GPU 编程与 CPU 多线程编程有着根本区别 。
这其中最根本的一个区别可以在上右图中看出,每一行有多个 Core,却只有一个 Control,这代表着多个 Core 同一时刻只能执行同样的指令,这种模式也称为 SIMT (Single Instruction Multiple Threads). 这与现代 CPU 的 SIMD 倒是有些相似,但却有根本差别,本文在后面会继续深入细究 。
从 GPU 的架构出发,我们会发现,因为 Cache 和 Control 的缺失,只有 计算密集 与 数据并行的程序适合使用 GPU 。
  • 计算密集:数值计算 的比例要远大于 内存操作,因此内存访问的延时可以被计算掩盖,从而对 Cache 的需求相对 CPU 没那么大 。
  • 数据并行: 大任务可以拆解为执行相同指令的小任务,因此对复杂流程控制的需求较低 。
而深度学习恰好满足以上两点,本人认为,即使存在比深度学习计算量更低且表达能力更强的模型,但如果不满足以上两点,都势必打不过 GPU 加持下的深度学习 。
FermiFermi 是 Nvidia 在 2010 年发布的架构,引入了很多今天也仍然不过时的概念,而比 Fermi 更早之前的架构,也已经找不到太多资料了,所以本文从 Fermi 开始,先来一张总览 。
揭秘英伟达 GPU 架构演进近十年,从费米到安培

文章插图
 
GPU 通过 Host Interface 读取 CPU 指令,GigaThread Engine 将特定的数据从 Host Memory 中拷贝到内部的 Framebuffer 中 。随后 GigaThread Engine 创建并分发多个 Thread Blocks 到多个 SM 上 。多个 SM 彼此独立,并独立调度各自的多个 Thread Wraps 到 SM 内的 CUDA Cores 和其他执行单元上执行 。
上面这句话有几个概念解释一下:
  • SM: 对应于上图中的 SM 硬件实体,内部有很多的 CUDA Cores;
  • Thread Block: 一个 Thread Block 包含多个线程(比如几百个),多个 Blocks 之间的执行完全独立,硬件可以任意调度多个 Block 间的执行顺序,而 Block 内部的多个线程执行规则由程序员决定,程同时程序员可以决定一共有多少个 Blocks;
  • Thread Warp: 32 个线程为一个 Thread Warp,Warp 的调度有特殊规则,本文后面会继续深入 。
由于本文不是讲怎么写 CUDA,所以如果对 SM/Block 的解释仍然不明白,可以参考这一小节:
https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#scalable-programming-model
上图存在 16 个 SMs,每个 SM 带 32 个 Cuda Cores,一共 512 个 Cuda Cores. 这些数量不是固定的,和具体的架构和型号相关 。
接下来我们深入看 SM,来一张 SM 总览:
揭秘英伟达 GPU 架构演进近十年,从费米到安培

文章插图
 
从上图可知,SM 内有 32 个 CUDA Cores,每个 CUDA Core 含有一个 Integer arithmetic logic unit (ALU)和一个 Floating point unit(FPU). 并且提供了对于单精度和双精度浮点数的 FMA 指令 。
SM 内还有 16 个 LD/ST 单元,也就是 Load/Store 单元,支持 16 个线程一起从 Cache/DRAM 存取数据 。
4 个 SFU,是指 Special Function Unit,用于计算 sin/cos 这类特殊指令 。每个 SFU 每个时钟周期只能一个线程执行一条指令 。而一个 Warp(32 线程)就需要执行 8 个时钟周期 。SFU 的流水线是从 Dispatch Unit 解耦的,所以当 SFU 被占用时,Dispatch Unit 会去使用其他的执行单元 。


推荐阅读