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,显存带宽是多少。再跑一个简单的矩阵乘法,对比一下用共享内存和不用共享内存的性能差异。动手试试,比看十遍文章都管用。