vLLM 显存装不下:参数该按什么顺序调
vLLM 部署最常见的崩溃场景不是模型跑得慢,是启动时或跑着跑着 OOM。这篇不讲原理,只讲参数该按什么顺序调、每个参数动下去代价是什么。
验证截至 2026-10-21。依据 vLLM 官方文档(Conserving Memory / Optimization / FP8 三章),并与公开技术分析交叉核对;括号内标注了确认时点的数值,请以你所运行版本的官方文档为准。
环境与版本
- 适用对象:vLLM 的
vllm serve与LLM两类接口,单卡到多机多卡均适用 - 版本敏感项:
gpu_memory_utilization的默认值在历史上变过,下文标注的 0.92 是 2026-08 在文档与CacheConfig源码中确认的值,旧教程里常见的另一个数字已经不适用 - 硬件相关:量化那一节的收益严格依赖显卡计算能力,见下文边界部分
先说结论:一次只改一个参数
调参最常见的失败不是选错了值,而是同时改了五六个值,最后既不知道哪个起作用,也没法回滚。
推荐的固定顺序是四步:
1. 先让模型装进显存
2. 再把长度上限对齐真实负载
3. 然后给 KV cache 留出余量
4. 最后才动 batch 和延迟
前三步没定下来就去调 batching 相关的参数,通常什么也不会发生——因为限制根本不在那儿。
第一步:gpu_memory_utilization 是第一个该动的值
官方定义:模型执行器可使用的显存比例,取值 0 到 1,默认 0.92。
它的机制决定了它为什么排第一:vLLM 先按这个比例把显存整块划走,扣掉模型权重和运行时开销之后,剩下的全部给 KV cache。所以调高它,KV cache 立刻变大,能同时接住更长和更多的请求。
但不要往 1 推,有两个理由:
- 它按整张卡计算。 卡上还跑着别的进程时(Kubernetes 里共享 GPU 是常态),这个比例算出来就是错的。
- 实际占用会比计算值高一截,来自显存碎片和瞬时激活张量。把余量压成 0 的典型后果是"大部分时候一切正常,某些请求组合下突然炸掉"。
一个有用的判据:如果调高它吞吐没有涨,说明瓶颈不在显存,卡住你的是 max_num_seqs 或 max_num_batched_tokens,继续拧这个旋钮没有意义。
第二步:长度上限和并发上限,直接对应 KV cache 的两个乘数
| 参数 | 作用 | 降下去的代价 |
|---|---|---|
max_model_len | 单条序列的最大 token 数 | 长文本会被截断或拒绝 |
max_num_seqs | 一批里的并发请求上限 | 并发上不去,请求开始排队 |
max_num_batched_tokens | 单批最大 token 数,影响 prefill 与 decode 的平衡 | 官方提到大于 8192 有利于吞吐,压太低会牺牲吞吐 |
KV cache 的需求大致就是"序列长度 × 并发数"的函数,所以装不下的时候不是玄学——降这两个值,需求按比例下来。选降哪个取决于你的负载:长文本为主就压并发上限,高并发短请求为主就压长度上限。
第三步:TP 是容量选项,不是性能选项
这是最普遍的一个误解。官方文档的判据很直接:
- 单卡放不下、单机多卡放得下 → 用 tensor parallelism
- 单机都放不下 → TP 加 PP(流水线并行)
- 取值:
tensor_parallel_size= 每节点 GPU 数,pipeline_parallel_size= 节点数。文档给的例子是 2 节点 × 8 卡 → TP=8、PP=2 - 例外:单节点内 GPU 无法均分时,可以设 TP=1、PP=GPU 数,让模型层做不均分切分
tensor_parallel_size 的默认值是 1。也就是说什么都不设,引擎就只用一张卡,哪怕机器上插了八张。多卡机器性能不及预期,第一个该查的就是这个值。
模型本来就能塞进一张卡时开 TP 会怎样:每张卡分到自己的 KV cache,总容量确实变大——这部分是真实收益;但每一层都多了卡间通信,而且是同步的。所以这不能算无条件的赢,得实测过再定。
官方给出的 OOM 缓解顺序
按顺序试,不要跳步,因为越往后代价越大:
1. 提高 gpu_memory_utilization(代价:留给别人的显存变少)
2. 降低 max_num_seqs 或 max_num_batched_tokens(代价:并发或吞吐下降)
3. 提高 tensor_parallel_size(代价:同步开销)
4. 提高 pipeline_parallel_size(代价:延迟)
另外有个容易被忽略的参数:kv_cache_memory 可以直接指定 KV cache 大小,跳过启动时的显存 profiling 阶段。profiling 结果不稳定、或者启动耗时太长时,这是个绕过去的办法。
量化这笔账要按硬件算
官方 FP8 文档的说法是:显存减半,吞吐最高提升 1.6 倍,精度影响很小。两个前提容易被跳过:
一是硬件门槛。 FP8 计算需要 NVIDIA 计算能力 ≥ 8.9(Ada Lovelace / Hopper / Blackwell)。Turing / Ampere 上会退化成仅权重的 W8A16,走 Marlin kernel——显存收益还在,但拿不到完整的 W8A8 加速。
二是 kernel 选择。 vLLM 在加载时自动挑 FP8 GEMM kernel,启动日志里会打一行 Selected。如果推理挂住且不报错,官方建议试 VLLM_USE_DEEP_GEMM=0 或 --linear-backend cutlass。注意 --linear-backend 只作用于量化线性层,MoE 专家走的是单独的 --moe-backend,别设错了以为生效了。
FP8 有两种表示,E4M3(范围小、精度高)和 E5M2(范围大、精度低),权重和激活的实际取值分布决定该用哪个。
边界与坑
- 显存要按权重 + KV cache + 余量三块估,只算权重就会在"看起来够"的情况下 OOM
- 所有参数都与版本绑定。跨版本升级后必须重查文档,尤其是配置项重命名这类破坏性变更
- 共享 GPU 场景下
gpu_memory_utilization的语义会失真,此时不如直接用kv_cache_memory锁死 - 调参期间一次只改一个值,否则无法归因
常见问题
Q:gpu_memory_utilization 是不是越高越好?
不是。它按整卡计算,共享 GPU 时会算错;且不留余量会在特定请求组合下突然 OOM。调到吞吐不再随它增长就够了。
Q:多卡机器性能上不去,先查什么?
tensor_parallel_size,它默认是 1。
Q:模型装得下,还有必要开 TP 吗?
KV cache 总量变大是真的收益,但每层多了同步通信。要测,不要默认开。
Q:量化一定能解决显存问题吗?
显存层面基本能,加速层面看硬件——计算能力低于 8.9 的卡拿不到完整 FP8。
参考与延伸
- vLLM 官方文档:Conserving Memory、Optimization、FP8 三章(
docs.vllm.ai,请以所运行版本为准) - 交叉核对:TT Lab Blog《Inside vLLM (7) — Deployment Tuning, Common Pitfalls, and OOM Triage》,2026-08-12,该文明确声明其数值核对至该日期
- 显存估算方法:权重 / KV cache / 余量三块拆分法,可与上述参数一一对应