显存基础: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的数据复用率,减少无效搬运,同时让更多请求共享一次权重读取。
显存带宽:推理吞吐的第一约束
对于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调参、批量大小设置、前缀缓存开关才有明确依据。显存容量决定“能不能跑”,显存带宽决定“跑多快”,而显存层次决定“优化空间有多大”——三者必须联动分析,才能找到吞吐优化的正确路径。