Skip to content

HBM 显存架构与带宽:从 HBM3e 到训练/推理带宽瓶颈 ​

说明:本篇为综述/无第一手实验数据,采用公开技术资料与架构解析路线。

实验目标 ​

为什么 2023 年之后的大模型训练,大家都在反复强调"显存带宽"而不是"显存容量"?答案藏在算力与带宽的增速剪刀差里:每一代 GPU 的 FP16 算力大约翻倍,而显存带宽只增长 40%-60%。以 H100 为例,BF16 稠密算力约 989 TFLOPS,HBM3 带宽约 3.35 TB/s——如果让计算单元"吃饱",每个字节的算术强度必须达到约 295 FLOP/B;而 Transformer 训练中相当比例的操作(注意力、归一化、梯度同步、参数加载)算术强度远低于这个值。本篇的目标是建立一个清晰的带宽核算框架:给定模型与集群配置,先算带宽够不够,再谈算力够不够,并给出可落地的排查与调优清单。

代码逐段拆解 ​

先看一段经典的"带宽核算"脚本。它用 PyTorch 的显存拷贝来测量可达带宽,这是判断"配置是否够用"的第一步:

python
import torch, time

def measure_bw(shape, iters=100):
    a = torch.randn(shape, device='cuda', dtype=torch.float16)
    b = torch.empty_like(a)
    # warmup:驱动与 CUDA context 初始化
    b.copy_(a); torch.cuda.synchronize()
    t0 = time.perf_counter()
    for _ in range(iters):
        b.copy_(a)
    torch.cuda.synchronize()
    dt = (time.perf_counter() - t0) / iters
    bytes_moved = 2 * a.numel() * a.element_size()  # 读 + 写
    return bytes_moved / dt / 1e12  # TB/s

# 32GB 显存的 H 级卡:32*0.9 可分配 ≈ 28GB
print(measure_bw((6_000_000_000,), iters=50), "TB/s 实测拷贝带宽")

逐段理解:

  1. copy_ 是带宽探针:一次 copy_ 要读整个张量再写整个张量,移动字节数 = 2 * numel * element_size,实测值接近理论带宽的 80%-90%(受 ECC、内存控制器开销影响)。这个数字就是后面一切估值的"基准带宽"。
  2. warmup 必须做:第一次 CUDA 调用要初始化 context、分配流处理器,不预热会把首次延迟算进带宽,造成假低值。
  3. synchronize 卡点:GPU 是异步的,不同步就计时,循环会全部入队后瞬间返回,测出假高值。
  4. 用 numel * element_size 而不是 nbytes 的差值:内存分配的对齐与页大小会造成 nbytes 虚高,按元素算更准确。

原理讲解 ​

从 GDDR 到 HBM:为什么带宽成了稀缺资源 ​

GDDR(如 GDDR6X)靠提高 I/O 频率堆带宽,代价是功耗高、PCB 走线长;HBM(High Bandwidth Memory)换了一条路——把内存 die 垂直堆叠,用硅中介层(interposer)短距离互连。堆叠解决容量(层数×单 die 容量),短互连解决带宽(走线短→可以加宽数据总线)。HBM3e 每个伪通道(pseudo-channel)独立编址与调度,一个堆叠有 8-16 个伪通道,访存并行度大幅提升。

关键数字对比(公开资料口径):

指标GDDR6X (RTX 40 系)HBM3 (H100)HBM3e (H200)HBM3e 12-Hi (B200)
单卡带宽~1 TB/s3.35 TB/s4.8 TB/s8 TB/s
单堆叠容量—16GB24GB36GB
位宽384-bit5120-bit5120-bit8192-bit

(数值为厂商公开规格,估算口径。)

带宽为什么卡住大模型 ​

以 70B 参数、BF16(140GB 权重)模型为例:

  • 推理逐 token 生成:每个 token 都要把全部权重从 HBM 读一遍,算术强度 ≈ 每 token 的 FLOPs / 权重字节数,通常只有几十 FLOP/B,远低于 GPU 的峰值算术强度。因此推理的 token 吞吐 ≈ 带宽 / 权重体积:H100 上约 3.35TB/s ÷ 140GB ≈ 24 token/s(单卡、单请求)。H200 带宽 4.8TB/s,同样模型直接提到 ~34 token/s——这就是"换 H200 推理更快"的底层原因。
  • 训练中的注意力与 RMSNorm:这两类算子访存密集(按 token 读 K/V、读统计量),不是算力瓶颈而是带宽瓶颈,所以 FlashAttention 的核心工作就是把"读 HBM → 算 → 写 HBM"改成"读一次 SRAM → 算完 → 只写回结果"。

带宽核算框架 ​

对任意配置,先按以下顺序核算:

  1. 权重加载带宽:推理吞吐 ≈ 可用带宽 ÷ 单卡权重字节(KV Cache 未命中场景)。
  2. 激活访存:训练中激活流量 ≈ batch_size × 序列长 × 隐藏维 × 层数 × 每层读写次数 × 字节数,用张量并行切分后按卡分摊。
  3. 通信带宽:AllReduce 流量在计算网络(ROCE)上走,不走 HBM——但梯度张量要先写回 HBM 再被 RDMA 读取,显存带宽不足会拖慢通信启动。
  4. 对比判定:若 模型总 FLOPs / 显存总带宽 > 单卡算力 / 单卡带宽 × 卡数,说明系统处于带宽受限区,加卡不加带宽收益递减。

实验结果 ​

用上述框架做三个典型估算(估算口径,供选型参考):

场景配置带宽估算结论
70B 推理(单卡 H100)140GB BF16~24 token/s换 H200 → ~34 token/s,带宽直换吞吐
70B 推理(H100 × 8 张 TP)每卡 17.5GB带宽按卡分摊,权重每卡 1/8吞吐≈单卡×8,但受 AllReduce 通信限制
7B 微调(单卡 A100 40G)权重 14GB + 优化器态带宽受限阶段:Adam 态读写在 1.5TB/s 上占大头优先用 ZeRO/FSDP 减显存占用,而非加卡

(以上为基于公开规格的估算,非实测数据。)

工程启示 ​

  1. 先量带宽,再谈算力:任何训练/推理系统上线前,先跑一遍上面的 measure_bw 得到"可达带宽"基线,把它写进硬件验收清单,与厂商标称值对比(一般 80%+ 为正常)。
  2. 推理选型看 HBM 带宽密度:同算力下,HBM 带宽更高的卡对长上下文和 LLM 生成更友好;"GB/s 每美元"比"TFLOPS 每美元"更贴近真实推理成本。
  3. 把 HBM 当稀缺资源设计:训练脚本里控制 activation checkpointing 的粒度、通信张量是否常驻显存、KV Cache 预留水位——每一笔显存流量都会挤占带宽。
  4. 监控带宽而不只监控利用率:nvidia-smi dmon -s m 里的 fb 利用率只是带宽的粗略代理,要精确看带宽需用 DCGM 或 Nsight Systems 的 memory workload 指标(下一篇会展开集群级可观测性)。

下一篇预告:本篇回答了"单卡带宽怎么看",下一篇进入集群视角——"GPU 集群可观测性:DCGM 监控体系与告警设计",讲清楚集群里每张卡的功耗、温度、带宽、SM 占用如何被统一采集与告警。

AI-HPC 智算超算专家 · Contact: openaihpc@gmail.com