1. GPU显存架构与基础概念

大家好,我是你们的讲师。今天咱们聊聊GPU显存——说白了,就是显卡上的“内存条”。我做了这么多年GPU集群,发现很多人对显存的理解停留在“越大越好”这个层面。嗯,其实远不止这么简单。

显存是GPU的“粮仓”。模型参数、中间激活值、梯度,全得塞在这里。一旦显存不够,训练就得停下来等数据搬运,那效率就惨不忍睹了。我个人习惯,拿到一块新卡,第一件事就是看它的显存拓扑。

显存类型:HBM vs GDDR

目前主流GPU显存就两种:HBM和GDDR。你想想看,这俩的区别就像高铁和普通火车——都能运货,但速度和容量完全不同。

特性 HBM (High Bandwidth Memory) GDDR (Graphics DDR)
典型带宽 1.6 - 3.2 TB/s 400 - 900 GB/s
单颗容量 4GB - 16GB 8GB - 32GB
功耗 较低(~1.5 pJ/bit) 较高(~3.5 pJ/bit)
典型应用 H100、A100、MI300X RTX 4090、RTX 6000

HBM 是堆叠式设计,说白了就是把多个DRAM芯片叠在一起,中间用硅通孔(TSV)连接。这样做的好处是——带宽极高。我在项目中遇到过,用HBM的A100跑大模型,显存带宽瓶颈几乎不存在。但代价是成本高,容量也受限。

GDDR 则是传统平面布局,走的是PCIe总线。优点是容量大、便宜。RTX 4090有24GB GDDR6X,价格只有A100的十分之一。但带宽就差远了。我曾经用RTX 4090跑175B模型,数据搬运成了最大瓶颈。

核心结论:训练大模型,首选HBM;推理或小模型,GDDR性价比更高。

显存带宽:为什么它比容量更重要?

很多人只看显存大小,忽略了带宽。我告诉你,带宽才是真正的“隐形杀手”。

显存带宽的计算公式很简单:

带宽 = 显存频率 × 位宽 × 通道数 / 8

举个例子:H100的HBM3显存,频率约2.6GHz,位宽5120位,通道数8。算下来:

带宽 = 2.6 × 10^9 × 5120 × 8 / 8 = 13.3 TB/s

嗯,你没看错,每秒13.3TB。而RTX 4090的GDDR6X,带宽只有1.0 TB/s左右。差了13倍。

为什么会这样?因为大模型训练时,每个计算步骤都要从显存读取大量数据。如果带宽不够,GPU计算单元就在“等数据”。我见过一个案例,某团队用RTX 4090跑LLaMA-65B,GPU利用率只有30%——因为显存带宽成了瓶颈。

避坑指南:我曾经以为显存够大就行,结果跑大模型时发现GPU利用率上不去。后来一查,是带宽不够。所以选卡时,带宽和容量要一起看。

显存容量:够用就好,不是越大越好

显存容量决定了你能装下多大的模型。但注意,不是越大越好——因为容量大了,带宽可能跟不上。

举个例子:A100有40GB和80GB两个版本。80GB版本用了HBM2e,带宽2.0 TB/s;40GB版本带宽1.6 TB/s。看起来80GB更好,但如果你模型只需要40GB,那多出来的40GB就是浪费——因为带宽没翻倍。

我建议这样估算显存需求:

  • 模型参数:每个参数约2字节(FP16)或4字节(FP32)
  • 优化器状态:Adam优化器需要额外8字节/参数
  • 梯度:每个参数2字节
  • 激活值:取决于batch size和序列长度,通常占30-50%

比如一个70B参数的模型,用FP16训练:

参数:70B × 2B = 140GB
优化器:70B × 8B = 560GB
梯度:70B × 2B = 140GB
激活值:约100GB
总计:约940GB

嗯,单卡根本装不下。这就是为什么需要多卡并行。

NVLink与PCIe拓扑:数据怎么在卡之间跑

多卡训练时,数据怎么在卡之间传输?这就涉及到NVLink和PCIe了。

PCIe 是通用接口,所有GPU都支持。但带宽有限——PCIe 4.0 x16只有32 GB/s,PCIe 5.0 x16是64 GB/s。相比HBM的TB级带宽,差了两个数量级。

NVLink 是NVIDIA的私有互联技术。它直接连接GPU,不经过CPU。NVLink 4.0每个链路带宽900 GB/s(双向),H100有18个NVLink链路,总带宽3.6 TB/s。

我画了一张图,帮你理解这两种拓扑:

GPU集群显存拓扑示意图 PCIe Switch CPU GPU 0 HBM3: 80GB GPU 1 HBM3: 80GB GPU 2 HBM3: 80GB GPU 3 HBM3: 80GB PCIe 4.0 x16: 32 GB/s NVLink: 900 GB/s NVLink: 900 GB/s NVLink: 900 GB/s PCIe 连接(慢速) NVLink 连接(高速) GPU 节点 NVLink 带宽是 PCIe 的 28 倍,适合模型并行通信 PCIe 适合数据搬运和初始化,训练时尽量用 NVLink

从图上你能看到,NVLink是GPU之间的“高速公路”,PCIe是“普通公路”。我建议:

  • 模型并行(Tensor Parallelism):必须用NVLink,因为通信量大
  • 数据并行(Data Parallelism):PCIe勉强够用,但NVLink更好
  • 流水线并行(Pipeline Parallelism):PCIe可以,但要注意带宽

注意:我曾经见过一个团队,8卡A100全部走PCIe,没有用NVLink。结果模型并行训练时,通信开销占了60%的时间。后来改成NVLink拓扑,训练速度提升了3倍。

实际项目中的显存调度策略

说了这么多理论,来点实战的。我在管理一个64卡H100集群时,总结了几条显存调度经验:

  1. 先看拓扑,再分配任务。用nvidia-smi topo -m查看GPU之间的连接方式,把通信密集的任务放在同一NVLink域内。
  2. 显存碎片化是隐形杀手。频繁申请释放显存会导致碎片。我习惯用torch.cuda.memory_summary()监控碎片率。
  3. 梯度累积 vs 显存占用。batch size太大显存不够?用梯度累积。但注意,累积步数越多,训练越慢。
  4. 混合精度训练。FP16/BF16能省一半显存,但要注意精度损失。我一般先用FP32跑一个epoch做基准。
# 查看GPU拓扑的实用命令
nvidia-smi topo -m

# 输出示例:
#        GPU0    GPU1    GPU2    GPU3
# GPU0   X       NV1     NV2     PHB
# GPU1   NV1     X       PHB     NV2
# GPU2   NV2     PHB     X       NV1
# GPU3   PHB     NV2     NV1     X
# 
# NV = NVLink, PHB = PCIe

嗯,看到NV标记的GPU之间,通信带宽是900 GB/s。PHB标记的只有32 GB/s。所以分配任务时,尽量把需要频繁通信的GPU放在同一NVLink组里。

一句话总结:显存调度不是简单的“够不够用”,而是“怎么用更高效”。带宽、拓扑、碎片,每个细节都可能成为瓶颈。