GPU架构基础:现代GPU计算核心、内存层次结构、PCIe与NVLink互联技术
好,咱们开始聊GPU架构。说实话,我最早接触GPU做计算时,还把它当显卡用。后来做分布式训练,才真正体会到——不理解GPU内部结构,你连性能瓶颈在哪都找不到。
这一节,我带你拆解三个核心模块:计算核心长什么样、内存怎么分层、芯片之间怎么通信。嗯,都是硬骨头,但啃下来,后面设计系统就顺了。
一、现代GPU计算核心:不止是“核”多
很多人以为GPU就是CPU的“多核版”。其实不是。CPU是几个强壮的壮汉,GPU是一群小蚂蚁——单个弱,但数量碾压。
以NVIDIA的Ampere架构为例,一个GA100芯片包含:
- 8192个CUDA核心(FP32单元)
- 128个SM(流式多处理器)
- 每个SM内部有64个FP32核心、32个FP64核心、4个Tensor Core
Tensor Core这东西,我印象特别深。2017年V100刚出时,我还在用P100做训练,一个BERT模型要跑三天。换了V100,Tensor Core一开,直接缩到十几个小时。说白了,它就是为矩阵乘法量身定做的硬件加速器。
关键点:GPU的并行不是“任务并行”,而是“数据并行”。同一个指令,喂给不同数据,同时算。这叫SIMT(单指令多线程)。
你想想看,CPU一个核跑一个线程,GPU一个SM能同时跑上千个线程。为什么?因为GPU的线程切换几乎零开销——它靠“隐藏延迟”来填满计算单元。一个线程等内存,立马切另一个线程算。
我的经验:写CUDA代码时,别怕线程多。我见过有人为了省线程数,把循环拆得乱七八糟,结果性能反而差。GPU喜欢“海量线程”,哪怕每个线程只做一点点事。
二、内存层次结构:速度与容量的博弈
GPU的内存,说白了就是金字塔结构。越往上越快,但越小。我画个表格,你一看就明白:
| 层级 | 容量 | 带宽 | 延迟 | 作用 |
|---|---|---|---|---|
| 寄存器 | 256KB/SM | 极高 | 1 cycle | 线程私有变量 |
| 共享内存 | 48-164KB/SM | 极高 | ~20 cycles | 线程块内通信 |
| L1缓存 | 128KB/SM | 高 | ~30 cycles | 数据局部性 |
| L2缓存 | 40MB(A100) | 中 | ~200 cycles | 芯片级共享 |
| HBM2e显存 | 80GB(A100) | 2TB/s | ~400 cycles | 全局数据存储 |
这里有个坑,我踩过。共享内存和L1缓存,在A100上是共用一块物理SRAM。你可以配置成48KB共享内存+128KB L1,或者反过来。我曾经为了省共享内存,把配置调成16KB共享内存+160KB L1,结果一个block里线程太多,共享内存不够用,程序直接崩了。
避坑指南:共享内存是手动管理的,L1是自动的。别指望编译器帮你优化共享内存的bank conflict。我曾经在一个矩阵转置核函数里,因为没处理好共享内存的bank冲突,性能直接腰斩。
再说显存。HBM(高带宽内存)是现在的主流。它不像DDR那样插在主板上,而是通过硅中介层和GPU芯片堆叠在一起。好处是位宽惊人——A100的HBM2e有5120位宽,带宽2TB/s。坏处是贵,而且容量有限。
我建议你记住一个原则:能放寄存器就别放共享内存,能放共享内存就别放显存,能放显存就别走PCIe。这个顺序,决定了你程序的性能天花板。
三、PCIe与NVLink:GPU之间的“高速公路”
单卡再强,也有极限。多卡协同,通信就是命门。
先讲PCIe。这是最通用的互联方式。PCIe 4.0 x16的单向带宽是16GB/s,双向32GB/s。听起来不低,但跟GPU内部带宽比,差了两个数量级。你想想看,A100显存带宽2TB/s,PCIe只有16GB/s——差了125倍。
所以,能不通过PCIe传数据,就别传。我早期做多卡训练,把梯度通过PCIe传到CPU再广播,结果通信占了60%的时间。后来换成NVLink,直接降到10%。
NVLink是什么?NVIDIA搞的私有互联技术。它不像PCIe那样走共享总线,而是点对点直连。每个NVLink链路是50GB/s(双向),A100有12个NVLink链路,总带宽600GB/s。
看个对比:
| 特性 | PCIe 4.0 x16 | NVLink 2.0(V100) | NVLink 3.0(A100) |
|---|---|---|---|
| 单向带宽 | 16 GB/s | 25 GB/s | 50 GB/s |
| 双向带宽 | 32 GB/s | 50 GB/s | 100 GB/s |
| 拓扑 | 树形/星形 | 混合立方体 | 全互联 |
| 延迟 | ~1μs | ~200ns | ~200ns |
| 支持GPU数量 | 不限(但共享带宽) | 最多8卡 | 最多8卡 |
NVLink还有一个杀手锏——GPU Direct P2P。两个GPU可以直接读写对方显存,不用经过CPU。我做过一个测试,8卡V100通过NVLink做all-reduce,通信时间比PCIe版本快了5倍。
核心结论:多卡协同,NVLink是首选。如果预算有限只能用PCIe,那就尽量用异步传输,把通信和计算重叠起来。我习惯用CUDA Stream,一个stream算,另一个stream传,能掩盖不少延迟。
最后说一句,NVLink不是万能的。它只支持同代GPU互联,而且最多8卡。如果你要搭32卡、64卡集群,还得靠NVSwitch——那是另一个话题了,后面章节会讲。
小结
这一节,我们聊了:
- GPU计算核心:SM、CUDA Core、Tensor Core,以及它们怎么协同工作
- 内存层次:从寄存器到HBM,每一级的速度、容量、用法
- 互联技术:PCIe和NVLink的带宽、延迟、适用场景
嗯,内容不少。但这些都是后面设计多GPU系统的地基。下一节,我们开始讲真正的分布式训练策略——数据并行、模型并行、流水线并行。到时候你会发现,今天讲的这些架构知识,全都能用上。
一个小练习:打开nvidia-smi,看看你的GPU有几个SM,显存带宽是多少。再跑一个简单的矩阵乘法,对比一下用共享内存和不用共享内存的性能差异。动手试试,比看十遍文章都管用。