显存基础:GPU显存层次、显存带宽与容量对推理性能的影响

核心原理:显存不只是“容量”一个维度

在讨论vLLM吞吐优化之前,必须先建立对GPU显存的正确认知。很多优化者只盯着“显存够不够用”,却忽略了显存层次和显存带宽这两个同样致命的维度。现代GPU(如NVIDIA A100/H100、AMD MI300X)的显存系统是一个分层结构,每一层的容量、带宽和延迟差异巨大,直接决定了推理引擎能做什么、不能做什么。

以NVIDIA H100 SXM为例,其显存层次从上到下大致为:

  • 寄存器文件(Register File):每个SM内部,总计约256KB,带宽极高(数十TB/s),但容量极小,仅能保存当前指令操作数。
  • L1缓存/共享内存(Shared Memory):每个SM约256KB,可配置为L1或共享内存,带宽约10~20TB/s,延迟约30周期。
  • L2缓存:H100拥有50MB L2,带宽约5~8TB/s,延迟约200周期,是所有SM共享的最后一级片上缓存。
  • HBM3显存(全局显存):容量80GB,带宽约3.35TB/s,延迟约400~600周期。这是KV Cache和模型权重的主要驻地。

推理性能的瓶颈往往不在计算单元(Tensor Core),而在数据搬运。一个典型的Transformer层前向计算中,权重矩阵和KV Cache都需要从HBM读取到SM,计算完成后结果再写回HBM。如果数据搬运速度跟不上计算速度,GPU就会处于“饥饿”状态,利用率低下。

关键认知:vLLM的PagedAttention、Continuous Batching等优化,本质上都是在提高HBM→SM的数据复用率,减少无效搬运,同时让更多请求共享一次权重读取。

GPU显存层次与推理数据流 SM(Streaming Multiprocessor) 寄存器文件 256KB / 数十TB/s L1 / 共享内存 256KB / ~15TB/s Tensor Core / CUDA Core 计算执行 Warp Scheduler 指令分发 片上互连 L2 缓存(所有SM共享) H100: 50MB / 带宽 ~6TB/s / 延迟 ~200周期 作用:缓存权重分片、KV Cache块、中间激活 HBM 接口(带宽瓶颈点) HBM 全局显存(主存储) 模型权重 7B≈14GB(FP16) 70B≈140GB(FP16) KV Cache 随并发请求增长 vLLM按需分配块 中间激活 / 临时缓冲 算子临时输出 通信缓冲 HBM3带宽 ≈ 3.35 TB/s(H100) | 延迟 ≈ 400~600周期 对比:L2带宽约6TB/s,寄存器带宽数十TB/s → 数据应尽量在片上复用

显存带宽:推理吞吐的第一约束

对于LLM推理,尤其是解码阶段(Decode),每个请求每次只生成一个Token,但需要读取整个模型的权重(以及该请求的KV Cache)。这意味着每次Token生成都伴随着全量权重的一次HBM读取。假设一个7B模型以FP16存储,权重大小为14GB,H100的HBM带宽为3.35TB/s,那么理论上每秒最多只能处理约239次全量权重读取(3.35TB/s ÷ 14GB ≈ 239次/s)。如果每个请求生成一个Token需要一次权重读取,那么整机吞吐上限就在每秒239个Token左右——即使计算单元完全空闲。

这就是为什么批量推理(Batching)如此重要:当多个请求组成一个Batch时,权重只需要从HBM读取一次,却可以服务多个请求的多个Token。vLLM的Continuous Batching正是通过动态拼接请求来最大化每次权重读取的“利用率”。

带宽利用率公式:有效吞吐 = 批量大小 × 单请求Token生成速率。批量越大,权重读取的摊销成本越低,但KV Cache占用也随之增加——这就是显存容量与带宽之间的核心权衡。

显存容量:决定并发上限与KV Cache策略

显存容量决定了能同时驻留多少请求的KV Cache。以7B模型为例,假设每个Token的KV Cache占用约0.5MB(取决于层数、头数、精度),那么一个拥有2048个Token上下文的请求,其KV Cache约为1GB。80GB的H100在加载14GB权重后,剩余约66GB可用于KV Cache,理论上可容纳约66个这样的请求。但实际中还要预留激活内存、CUDA上下文、碎片空间等,可用容量通常只有理论值的70%~80%。

vLLM的PagedAttention机制将KV Cache划分为固定大小的块(通常16个Token一块),以类似虚拟内存的方式管理。这样做的好处是:

  • 消除内部碎片:传统方法为每个请求预分配最大长度空间,浪费严重;分页按需分配,利用率接近100%。
  • 支持共享前缀:多个请求共享相同的系统提示词时,KV Cache块可以复用,进一步节省显存。
  • 灵活调度:块级管理让vLLM可以随时将不活跃请求的块换出,为高优先级请求腾出空间。

案例:显存带宽瓶颈的实测对比

我们在一台8×A100 80GB的服务器上,对同一个13B模型(FP16,权重约26GB)进行推理测试。使用vLLM,分别设置--max-num-seqs为1、8、32、64,测量吞吐量(Token/s)和显存占用:

批量大小 吞吐量(Token/s) 显存占用(GB) 带宽利用率 瓶颈类型
1 ~128 27.5 ~12% 带宽严重空闲,延迟主导
8 ~890 31.2 ~68% 带宽接近饱和
32 ~1150 42.8 ~88% 带宽饱和,接近上限
64 ~1180 58.3 ~91% 带宽饱和,显存余量不足

从表中可以看到:批量从1增加到32时,吞吐提升了约9倍,但继续增加到64时,吞吐几乎不再增长——因为HBM带宽已经用尽。此时再增加并发只会增加KV Cache占用和调度开销,不会带来吞吐收益。这个案例清晰地展示了显存带宽是比显存容量更先触顶的资源。

误区与复盘:常见显存认知偏差

误区一:认为“显存够用”就等于“性能好”。很多工程师只检查nvidia-smi显存占用率,看到剩余50%就认为可以继续加并发。实际上,当批量增大到一定程度后,带宽成为瓶颈,显存剩余再多也无法提升吞吐。正确做法是监控GPU利用率和内存带宽利用率(通过DCGM或Nsight Compute),而非仅看容量。

误区二:忽略L2缓存命中率对“有效带宽”的影响。当多个请求共享相同的系统提示词或前缀时,L2缓存可以缓存部分KV Cache块,减少HBM读取。vLLM的--enable-prefix-caching参数正是利用这一点。如果关闭该功能,相同前缀的重复计算会白白消耗HBM带宽。

误区三:把KV Cache预估得过于乐观。KV Cache大小不仅取决于模型层数和头数,还受GQA(Grouped Query Attention)影响。使用MHA(Multi-Head Attention)的模型KV Cache远大于使用GQA的模型。例如,Llama 2 70B使用GQA,其KV Cache比同规模MHA模型小约4~8倍。选型时必须确认注意力机制类型。

复盘建议:在优化吞吐前,先用vllm --profile或Nsight Compute做一次带宽剖析,确认当前瓶颈是HBM带宽、L2带宽还是计算单元。只有定位到真实瓶颈,后续的PagedAttention调参、批量大小设置、前缀缓存开关才有明确依据。显存容量决定“能不能跑”,显存带宽决定“跑多快”,而显存层次决定“优化空间有多大”——三者必须联动分析,才能找到吞吐优化的正确路径。