4. 硬件架构基础:NVIDIA GPU的SM、Warp、Tensor Core架构解析
聊GPU架构,很多人一上来就盯着显存带宽、算力这些数字看。我个人习惯,先看SM。为什么?因为SM才是GPU真正的计算核心,其他都是为它服务的。
说白了,一个NVIDIA GPU就是一堆SM的集合。每个SM都是一个独立的小型处理器,有自己的寄存器、共享内存、调度单元。你写的CUDA代码,最终就是在这些SM上跑的。
4.1 SM:GPU的心脏
SM的全称是Streaming Multiprocessor,流式多处理器。你可以把它理解成一个迷你CPU核心,但设计思路完全不同。
CPU核心追求单线程性能,有巨大的缓存、复杂的分支预测。SM追求的是吞吐量,它同时管理成百上千个线程。我刚开始接触CUDA时,总拿CPU的思路去优化GPU代码,结果性能惨不忍睹。后来才明白,SM的设计哲学就是「人多力量大」。
每个SM内部包含:
- CUDA Core:执行整数和浮点运算的基本单元
- Tensor Core:专门做矩阵乘法的加速单元
- 共享内存:同一个Block内的线程可以访问
- 寄存器文件:每个线程私有的高速存储
- Warp调度器:负责把指令发给执行单元
嗯,这里要注意。不同代的GPU,SM内部结构差异很大。比如Ampere架构的SM有4个分区,每个分区包含16个INT32单元、16个FP32单元、8个FP64单元。而Hopper架构又做了调整。你写代码时,最好查一下目标GPU的具体参数。
4.2 Warp:GPU的调度单位
Warp是NVIDIA GPU最核心的概念之一。一个Warp包含32个线程,它们以SIMT(单指令多线程)方式执行。什么意思?就是32个线程执行同一条指令,但处理不同的数据。
我曾经踩过一个坑。写了一段代码,里面有个if-else分支。32个线程里,16个走if,16个走else。结果呢?性能直接腰斩。因为Warp内的线程必须执行相同的指令,遇到分支时,一部分线程执行,另一部分就得等着。
关键点:Warp是GPU调度的最小单位。一个Warp内的线程必须同步执行。如果出现分支发散,性能会严重下降。
为什么会这样?因为SM里的Warp调度器一次只能给一个Warp发指令。它把32个线程绑在一起,统一调度。你想想看,如果32个人要干两件不同的事,那只能先让16个人干完,再让另外16个人干。效率自然低。
所以写CUDA代码时,我建议你尽量保证Warp内线程的执行路径一致。实在避免不了分支,那就让分支尽量简单,或者用三元运算符替代if-else。
4.3 Tensor Core:AI计算的加速引擎
Tensor Core是NVIDIA在Volta架构引入的专用硬件单元。它专门做矩阵乘法累加运算,也就是D = A × B + C。这个操作在深度学习里太常见了,全连接层、卷积层、注意力机制,本质上都是矩阵运算。
我记得第一次用Tensor Core时,被它的性能吓了一跳。同样是做矩阵乘法,用CUDA Core需要几百个时钟周期,Tensor Core一个周期就能完成4×4矩阵的乘法累加。这差距,简直不是一个时代的产物。
Tensor Core的工作原理是这样的:
- 输入矩阵A和B是半精度浮点数(FP16)
- 累加矩阵C可以是FP16或FP32
- 输出矩阵D的精度取决于累加矩阵
你可能会问,为什么用半精度?因为AI模型对精度的要求没那么高。FP16的数值范围虽然小,但做推理和训练足够了。而且半精度数据占用的显存少,带宽需求低,计算速度更快。
实战技巧:使用Tensor Core时,记得用cublasGemmEx或cuBLASLt API。手动写WMMA(Warp Matrix Multiply Accumulate)代码虽然灵活,但调试起来很痛苦。我建议先用库函数,性能瓶颈时再考虑手写。
4.4 三者如何协同工作
SM、Warp、Tensor Core不是孤立的。它们之间的关系,我画了一张图来说明:
这张图展示了一个SM内部的工作流程:
- Warp调度器从Warp Pool中选取一个就绪的Warp
- 根据指令类型,将Warp分发给CUDA Core或Tensor Core
- 执行单元完成计算后,结果写入共享内存或寄存器
- 共享内存作为Block内线程的通信桥梁
实际运行时,SM会同时管理多个Warp。当一个Warp在等待内存访问时,调度器会立刻切换到另一个Warp。这种机制叫「零开销上下文切换」,是GPU高吞吐量的关键。
避坑指南:我曾经在项目里遇到一个性能问题,显存带宽利用率只有30%。排查了半天,发现是共享内存使用过多,导致每个SM上活跃的Warp数量减少。记住,共享内存是有限的,用多了会限制并行度。
4.5 不同架构的差异
NVIDIA的GPU架构一直在演进。我整理了一个表格,方便你对比:
| 架构 | SM内分区 | 每个SM的CUDA Core | Tensor Core版本 | 共享内存大小 |
|---|---|---|---|---|
| Volta (V100) | 4个分区 | 64 FP32 + 64 INT32 | 第1代 | 96 KB |
| Turing (T4) | 4个分区 | 64 FP32 + 64 INT32 | 第2代 | 64 KB |
| Ampere (A100) | 4个分区 | 64 FP32 + 64 INT32 + 32 FP64 | 第3代 | 192 KB |
| Hopper (H100) | 4个分区 | 128 FP32 + 64 INT32 | 第4代 | 228 KB |
从表格可以看出,Tensor Core的迭代速度很快。第4代Tensor Core支持了FP8精度,进一步提升了AI计算的效率。我建议你在选择GPU时,优先考虑Tensor Core的代数,它对AI workloads的影响最大。
嗯,最后说一句。理解SM、Warp、Tensor Core的架构,是写出高性能CUDA代码的基础。你不需要记住每个细节,但一定要明白它们的设计意图。SM追求吞吐量,Warp是调度单位,Tensor Core是AI加速器。这三者配合好了,你的程序才能跑出接近理论峰值的性能。
核心总结:
- SM是GPU的计算核心,管理数百个线程
- Warp是32个线程的集合,是调度和执行的单位
- Tensor Core是专用矩阵乘法单元,大幅提升AI计算效率
- 避免Warp发散,合理使用共享内存,是优化的关键