Inference Engineering · 2026

vLLM 部署前沿大模型
从显存算术到并行拓扑

当模型来到 2.8 万亿参数(Kimi-K3.1-Pro,Qwen3.8 亦有 2.4T)、上下文来到 100 万 token,部署的难点已经从「装得下」变成「算得清」: 权重、KV Cache、通信、批调度四本账必须同时算平。这份手册以 vLLM 0.33 与官方 Recipes 为准, 把参数的含义、取值依据、以及不同硬件下的完整命令逐条拆开。

引擎vLLM 0.33.0
发布2026-11-02
Python3.11 – 3.14
覆盖模型13 个前沿系列

00导读与数据基准

先说清楚这份文档的边界:它讲什么、数据从哪来、哪些结论会随版本失效。

2026 年的开源模型迭代速度已经超过文档更新速度。本文所有参数释义、默认值、启动命令,均取自 vLLM 官方文档(docs.vllm.ai,页面更新于 2026-10-30)与 vLLM Recipes 仓库(recipes.vllm.ai,逐模型 YAML,最后更新 2026-11-05);模型规模与架构取自各模型 config.json 与官方模型卡实测值,不是估算。

为什么以 Recipes 为准

vLLM 官方维护了一套逐模型的 YAML 配方(recipes/models/<org>/<model>.yaml),里面不仅有验证过的启动命令,还有 每个精度变体的最小显存、已验证的硬件列表、最低 vLLM 版本。这比博客和二手教程可靠得多——本文的模型表格几乎全部来自这里。

三个必须先建立的心智模型

① 权重决定「能不能跑」

稀疏 MoE 让总参数和激活参数脱钩。DeepSeek-V4-Pro 是 1.6T 总参 / 49B 激活,权重仍要按 1.6T 算显存,但每 token 的计算量只按 49B 算。所以「参数大」不等于「慢」,但一定等于「贵」。

② 注意力架构决定「能开多长」

MLA 把 KV 压成低秩潜向量;DSA / MSA / CSA 再叠加稀疏选择;GDN / KDA 用线性注意力把状态变成常数。同样是 1M 上下文,不同模型的 KV 增速相差一个数量级。

③ 并行拓扑决定「快不快」

MoE 模型默认不再是 TP,而是 DP(注意力)+ EP(专家)。选错拓扑,即便显存够,吞吐也可能只有最优配置的三成。

④ 版本决定「有没有这个开关」

0.33.0 是当前稳定版。若某模型要求 ≥0.34.0(如 Kimi-K3.1-Pro、Mistral-Large-4),意味着必须用 day-0 镜像,稳定版 wheel 里没有对应代码路径。

版本与兼容性基线

组件基线说明
vLLM0.33.02026-11-02 发布,当前最新稳定版
Python≥3.11, <3.15官方 wheel 的 requires_python
CUDA12.8 / 13.0Blackwell 建议 cu130 镜像
ROCm7.0 / 10.0MI355X 新特性多在 ROCm 10 nightly
引擎架构V1V0 已在 0.11 起移除;本文全部按 V1 描述
时效性声明

模型的支持状态、内核后端自动选择策略、默认值都在快速变化。凡是涉及「默认值」的判断,请在目标机器上执行 vllm serve --help 或查看启动日志确认,不要照抄本文数字。

012026 的部署格局

三个结构性变化,让 2025 年的部署经验基本失效。

变化一:稀疏 MoE 成为默认形态

2025 年的主流还是 70B 稠密模型;2026 年的旗舰清一色是细粒度专家混合。激活比例被压到 3%–6%,这意味着显存瓶颈和算力瓶颈彻底分离:你需要为 1.6T 参数准备 HBM,但每 token 只激活 49B,单卡算力反而不是主要矛盾,跨卡通信才是。

1.6T
DeepSeek-V4-Pro 总参数
3.1%
激活比例(49B / 1.6T)
896
Kimi-K3 路由专家数
1M
旗舰模型标准上下文

变化二:上下文进入百万级

DeepSeek-V4 系列、Kimi-K3、MiniMax-M3、GLM-5.3、Mistral-Large-4 都标称 1,048,576 token;Qwen3.5 原生 262,144,通过 YaRN 可扩到约 101 万。这带来两个直接后果:

  • Prefill 变成主要成本。一次 1M token 的 prefill 计算量相当于生成数万 token,必须靠 chunked prefill 和 PD 分离来隔离。
  • KV Cache 的绝对值仍然惊人。即便压缩到 10%,1M 上下文 × 高并发的 KV 需求依然会吃掉整机 HBM。

变化三:注意力架构分道扬镳

架构族代表模型KV 增长部署含义
MLA(多头潜注意力)DeepSeek-V3/V4、GLM-5、Kimi极低,按潜向量存长上下文友好,但需要 fp8_ds_mla 等专用 KV 量化
稀疏注意力(DSA / MSA / CSA+HCA)DeepSeek-V4、GLM-5.3、MiniMax-M3额外索引器状态需要 indexer_kv_dtype 独立配置,算子后端有强绑定
线性注意力混合(GDN / KDA)Qwen3.5、Kimi-K3、Qwen3.8常数状态 + 周期性全注意力需要 Mamba cache 管理,--max-num-seqs 受 cache block 数限制
GQA + 滑窗gpt-oss、Llama 系线性、可预测调优逻辑最经典,适合做基线

2026 前沿模型一览

下表为本文覆盖的 11 个系列。显存列为官方 recipe 给出的最小可加载 GPU 显存(含 1.2 倍余量),不是推荐值。

模型总参 / 激活上下文注意力精度最小显存vLLM
DeepSeek-V4-Pro 1.6T / 49B1,048,576 CSA + HCA 混合FP4+FP8960 GB≥0.20
DeepSeek-V4.1-Flash 552B / 8B·16B1,048,576 SWA + CSA,双层索引FP8614 GB≥0.31
Qwen3.5-397B-A17B 397B / 17B262,144 → 1.01M GDN + 每 4 层全注意力BF16/FP8/NVFP4/INT4953 / 477 / 238≥0.17
Kimi-K3.1-Pro 2.8T / 16 of 8961,048,576 KDA + 稀疏 MLAMXFP41,874 GB≥0.34
GLM-5 744B / 40B202,752 MLA + DSABF16/FP8/NVFP41786 / 893 / 446≥0.24
GLM-5.3 743B / 39B1,048,576 MLA + DSA,5-token MTPFP8/NVFP4/INT4893 / 558 / 447≥0.29
MiniMax-M3 427B / 26B1,048,576 MSA 块稀疏,原生多模态BF16/MXFP8/NVFP41025 / 513 / 257≥0.24
ERNIE-5.5-Flash 280B / 14B1,048,576 HCA + MLA-DSA,ECHO MTPFP8/BF16347 / 688≥0.32*
Mistral-Large-4 1T / 49B1,048,576 稀疏 MLA + DSparkNVFP4/FP8/MXFP4733 / 1273 / 694≥0.34
Qwen3.8-Flash-Next 176B / 6B262,144 Qwen4 预览,GDN + GQANVFP4/FP8/BF16/MXFP4130 / 250 / 423≥0.30
gpt-oss-120b 117B / 5.1B131,072 滑窗 + 全注意力交替MXFP496≥0.10

* ERNIE-5.5-Flash 需额外安装 vLLM-ERNIE 插件,且插件锁定 0.32.0。

落地前必读

0.34.0 尚未发布。Kimi-K3.1-Pro、Mistral-Large-4 要求 0.34.0,目前只能通过 day-0 镜像(vllm/vllm-openai:kimi-k31、vllm/vllm-openai:mistral-large-4)运行,且官方明确「pip 安装不可用」。这类模型的部署计划必须把镜像版本钉死,不能依赖 pip install -U vllm。

02显存预算与 KV 计算

部署第一步不是敲命令,是算账。算错一个数量级,你会花两天在 OOM 里打转。

显存的四块开销

vLLM 启动后,一张卡的 HBM 被切成四份。理解这四份的比例,才知道该调哪个旋钮。

单卡 HBM 预算分解(示意:8×H200 跑 397B FP8) 权重 Weights 激活 工作区 KV Cache 图/碎片 0 ≈50 GB ≈61 GB ≈130 GB 141 GB 由精度与量化决定 唯一不可压缩的硬成本 由 --gpu-memory-utilization 反推 真正决定并发上限的部分 注:比例为量级示意;vLLM 启动日志会打印实际可用 KV token 数。
图 1. 显存预算。权重是刚性成本,KV Cache 是唯一可以被调度和量化的弹性空间;--gpu-memory-utilization 控制的正是「权重之外还能占多少」。
区块内容控制手段
权重模型参数、embedding、LM head换精度(FP8/NVFP4/INT4)、换 checkpoint、加 TP/EP
激活与工作区前向中间张量、MoE all-to-all 缓冲、FlashInfer workspace--max-num-batched-tokens、--max-num-seqs
KV Cache分页的 K/V 块 + 稀疏索引器状态 + Mamba 状态--kv-cache-dtype、--block-size、--gpu-memory-utilization
图与碎片CUDA Graph 捕获、显存碎片--max-cudagraph-capture-size、--enforce-eager

KV Cache 的两种算法

不同注意力架构的 KV 计算方式完全不同,用错公式会差出十倍。

MHA / GQA / MQA:同一公式,不同取值

这三种架构用的是同一个公式,差别只在 n_kv_heads 取什么值。把「GQA / MHA」并列成一个类别容易让人误以为两者算法不同,实际上是分组比 g 倍的关系。

公式 · MHA / GQA / MQA
# bytes per token, per sequence
KV = 2 × n_layers × n_kv_heads × head_dim × dtype_bytes
#        ↑ K 和 V 各一份   ↑ 唯一的架构差异在这里

# MHA: n_kv_heads = n_heads        → 1×    
# GQA: n_kv_heads = n_heads / g    → 1/g   
# MQA: n_kv_heads = 1              → 1/n_heads

# example: Llama-3.3-70B, bf16 (64 q-heads / 8 kv-heads, g=8)
# 2 × 80 × 8 × 128 × 2 = 327,680 B ≈ 320 KiB / token
# 同一个模型若用 MHA(64 kv-heads)→ 2.56 MiB/token,整整 8 倍
# 8k 上下文单请求就要 2.6 GB —— 这就是 GQA 模型的并发天花板
架构n_kv_heads相对 MHA 的 KV 量典型模型
MHA= n_heads1×Llama-1/2、GPT-3
GQA= n_heads / g1/gLlama-3(g=8)、Qwen3(g=8)
MQA= 11/n_headsPaLM、Falcon

MLA 模型(DeepSeek / GLM / Kimi 系)

公式 · MLA
# MLA 只缓存低秩潜向量 + RoPE 分量,不存完整 K/V
KV = n_layers × (kv_lora_rank + qk_rope_head_dim) × dtype_bytes

# example: DeepSeek-V3 / R1, bf16
# 61 × (512 + 64) × 2 = 70,272 B ≈ 68.6 KiB / token

# example: GLM-5, fp8 (1 byte)
# 78 × (512 + 64) × 1 = 44,928 B ≈ 43.9 KiB / token
# 同样 fp8 下,GLM-5 每 token 只有 Llama-70B 的 1/7
稀疏注意力的额外开销

DeepSeek-V4 的 CSA/HCA、GLM-5.3 的 DSA、MiniMax-M3 的 MSA 都会额外维护索引器状态(indexer K),而且这部分通常不跟随主 KV 一起量化。Kimi-K3 的 KDA 层还会为每条序列保留常数大小的循环状态,这部分不在分页 KV 池里,会额外吃显存。所以:稀疏模型的真实 KV 占用 = 公式值 + 索引器 + 状态池,务必以启动日志为准。

算一算:KV Cache 计算器

改下面任意一项,立刻看到每 token 开销与可容纳的上下文条数。

KV Cache 估算

按单序列、单 rank 计算;不考虑索引器与碎片开销。

—
每 token 显存
—
预算可容纳 token 总数
—
可并发的 32K 请求数

读懂启动日志

vLLM 启动完成时会打印两行关键信息,它们是唯一的权威数据:

启动日志(vLLM 实际输出)
INFO [kv_cache_utils.py] GPU KV cache size: 643,232 tokens
INFO [kv_cache_utils.py] Maximum concurrency for 40,960 tokens per request: 15.70x
  • 第一行是实际可容纳的 token 总数——不是字节数,是所有并发请求共享的池子。
  • 第二行按 max_model_len 折算并发数。这里的 40960 来自模型配置,不是你设的 --max-model-len。
  • 两行数字偏小 → 加卡、降精度、开 KV 量化、或缩短 --max-model-len。
跳过显存测量的技巧

启动日志还会打印一个 --kv-cache-memory 值,把这个值原样传回去(亦作 --kv-cache-memory-bytes),下次启动就能跳过 profiling 和 CUDA graph 显存估算,冷启动快数十秒。但它只在「同 GPU、同初始空闲显存」下有效;换了硬件或同机有其他进程,必须去掉该参数重新测量。

03架构与参数作用点

知道参数作用在哪个进程,才能判断它影响的是延迟、吞吐,还是启动时间。

V1 多进程架构

vLLM V1 把服务拆成三类进程。每一类都吃 CPU,都可能是瓶颈。

Client HTTP / SSE API Server × A HTTP / 分词 / 媒体加载 chat template · 流式回包 --api-server-count 媒体加载线程数 默认 A = DP ZMQ Engine Core × DP 调度器 · KV 块管理 忙循环(busy loop) 每步 token 预算 --scheduling-policy 每个 DP rank 一个 GPU Worker × N 每卡一个进程 GPU 0 · 前向 + KV GPU 1 · 前向 + KV ⋮ GPU N−1 N = DP × PP × TP NCCL / DeepEP 通信 DP Coordinator(仅 DP>1) 总计 A + DP + N 个进程(DP>1 时再加 1)。每个进程都要占 CPU 核。
图 2. V1 进程模型。API Server 负责输入处理(分词、模板、多模态),Engine Core 负责调度与 KV 管理,GPU Worker 只做前向。参数标注在它真正生效的进程上。媒体线程数对应 VLLM_MEDIA_LOADING_THREAD_COUNT;每步 token 预算对应 --max-num-batched-tokens。
最常见的性能杀手:CPU 核数不足

官方明确要求:至少 2 + N 个物理核(1 个 API Server + 1 个 Engine Core + 每卡 1 个 Worker)。开启 DP 后公式变为 A + DP + N + (DP>1 ? 1 : 0)。例如 DP=4, TP=2 跑 8 卡,共有 4 + 4 + 8 + 1 = 17 个进程。Engine Core 是忙循环,CPU 被抢占会直接表现为 GPU 利用率上不去——很多人误以为是 GPU 或模型问题。

一次请求的路径,与参数的作用位置

① 接入 HTTP / 鉴权 SSE 建连 ② 输入处理 分词 · 模板 图片/视频解码 ③ 排队调度 token 预算 抢占 / 分块 ④ KV 分配 前缀命中 块回收 ⑤ 前向 prefill / decode 采样 ⑥ 输出 反分词 流式推送 --tokenizer-mode --limit-mm-per-prompt --api-server-count --max-num-batched-tokens --max-num-seqs --scheduling-policy --enable-prefix-caching --block-size --kv-cache-dtype --tensor-parallel-size --speculative-config -O2 / cudagraph 延迟归属:②④⑥ 与 CPU 强相关 · ③ 决定排队时长(TTFT 主因) · ⑤ 决定 ITL 与吞吐
图 3. 请求生命周期。TTFT 的三大来源是排队、prefill、首 token 采样;ITL 几乎完全由 decode 阶段的前向决定。调优前先确定自己优化的是哪一个。

04核心参数详解

不是罗列所有参数,而是讲清那些「改了就出事」或「改了就有收益」的。

4.1 模型与精度

参数默认含义与取舍
--model— HF 仓库名或本地路径。生产环境务必用本地路径,避免启动时联网。国内网络设置 VLLM_USE_MODELSCOPE=True 走 ModelScope。
--dtypeauto 权重与激活精度。auto 会把 FP32/FP16 模型转成 FP16、BF16 模型保持 BF16。不要手动指定 bfloat16 去「强制」一个 FP8 checkpoint——那会绕过量化的 scale 路径。
--quantization从 config 推断 模型自带 quantization_config 时无需指定。只有做在线量化(如 --quantization fp8 量化 fp16 权重)才需要显式传。
--kv-cache-dtypeauto KV 存储精度。可选 fp8/fp8_e4m3/fp8_e5m2/nvfp4/fp8_ds_mla/int4_per_token_head 等十余种。FP8 KV 通常是最划算的一档:显存减半,精度损失可忽略。fp8_ds_mla 专为 DeepSeek 系 MLA 设计。
--max-model-len从 config 推断 prompt + output 的总长度上限。支持 1k/1K/25.6k 人类可读格式,-1 或 auto 表示「塞得下多少用多少」。调小它是解决 OOM 最快的手段,但对长文场景是硬伤。
--tokenizer-modeauto 2026 年的关键参数。DeepSeek-V4 用 deepseek_v4,Kimi-K3 用 kimi_k3,GLM-5.3 用 glm5_next。这些模型不再依赖 Jinja chat template,而是用 Python/Rust 渲染器。不设这个参数,工具调用和推理模式会全错。
--trust-remote-codeFalse 加载模型自带的 Python 代码。前沿模型几乎都必须开。安全上是把执行权交给模型仓库,只在你信任来源时使用。
--block-size视后端而定 KV 块的 token 数。DeepSeek-V4 官方推荐 256,GLM 系常用 128,Kimi-K3 用 64。改小 → 碎片少、前缀匹配更细;改大 → 元数据开销低、但浪费尾部空间。
FP8 KV 值不值得开

值得,而且几乎是必开。MLA 模型 fp8 KV 让每 token 从 68.6 KiB 降到 34.3 KiB,Kimi-K3 的 NVFP4 KV 甚至把每 token 每层从 576 B 降到 352 B(约 1.5 倍容量),而 GSM8K 从 96.2% 只掉到 96.1%。唯一要注意:滑窗层对 KV 量化更敏感,可用 --kv-cache-dtype-skip-layers sliding_window 把这些层留在原精度。

4.2 显存与并发

参数默认含义与取舍
--gpu-memory-utilization0.92(部分场景 1.0) 本实例最多占用多少比例的显存。不是「用了多少」,是「允许用到多少」。同卡多实例时各设 0.5 即可共存。调高 → KV 更大、并发更高,但留给激活的空间变小,长 prompt 易 OOM。
--kv-cache-memory-bytesNone 直接指定 KV 字节数,设置后忽略 gpu-memory-utilization。支持 40G/37580963840。适合需要精确控制、或与其它进程共卡的场景。
--max-num-seqs测试用默认值 单次迭代最多处理多少条序列。它同时决定 CUDA Graph 的捕获规模和常驻缓冲大小。调小 → 尾延迟更稳;调大 → 吞吐高但 ITL 抖动。
--max-num-batched-tokens随模型 单次迭代的 token 预算。这是最重要的吞吐/延迟旋钮:设 2048 时 ITL 最优(prefill 少打扰 decode);设 >8192 时 TTFT 最优(一次吃完长 prompt)。官方建议大卡小模型用 >8192。
--enforce-eagerFalse 关闭 torch.compile 与 CUDA Graph,等价于 -cc.mode=none -cc.cudagraph_mode=none。启动最快、稳态最慢。仅用于开发调试或显存极度紧张。
--max-cudagraph-capture-size512(Blackwell 数据中心卡 1024) CUDA Graph 捕获的最大 batch。过大 → 启动慢、显存吃紧;过小 → 大批次回退到 eager,吞吐掉。有投机解码时需按 S×(K+1) 重算。
--cpu-offload-gb0 每卡卸载多少 GiB 权重到 CPU,通过 UVA 零拷贝访问。需要极快的 CPU-GPU 互联,否则每层前向都变成 PCIe 瓶颈。只在「就差一点装不下」时用。

4.3 并行

参数含义何时用
--tensor-parallel-size / -tp层内切分权重,每层后 all-reduce单机装不下;或想给 KV 腾显存。要求 attention head 数能被 TP 整除。
--pipeline-parallel-size / -pp按层切分,跨 stage 传激活跨节点、或卡间无 NVLink(如 L40S);支持不整除的切分。
--data-parallel-size / -dp复制完整模型,各 rank 处理不同请求显存够、要堆吞吐。MoE 模型几乎必用。
--enable-expert-parallel / -epMoE 专家分散到多卡,代替 TPMoE 模型的默认选择。EP 规模 = TP × DP,自动计算。
--all2all-backendEP 的通信实现单机默认 allgather_reducescatter;prefill 密集用 deepep_high_throughput;decode 密集用 deepep_low_latency;ROCm 用 mori。
--decode-context-parallel-size / -dcp把 MLA 潜变量与索引器 KV 切成多份长上下文 + 多会话。Kimi-K3 在 DCP8 下 KV 容量约为 TP8 的 7 倍,代价是 decode 慢 7–25%。
--numa-bind启动前用 numactl 绑定 worker 到 GPU 本地 NUMA多路服务器。默认在满足条件时自动绑定;--numa-bind-nodes 可显式指定每卡的 NUMA 节点。

4.4 调度与缓存

Chunked prefill 在 V1 中默认开启,且调度器优先满足 decode。这条策略决定了 --max-num-batched-tokens 的双向效应:

同一请求流在两种 token 预算下的调度差异 预算 = 2048 ITL 优先 prefill 块 D prefill 块 预算 = 16384 TTFT 优先 长 prefill 一次吃完 长 prefill 一次吃完 prefill(计算密集) decode(访存密集) 预算小 → decode 被打断少,ITL 平稳;预算大 → 长 prefill 更快结束,TTFT 更低,但 decode 被拖住。
图 4. Chunked prefill 的双向效应。这张图解释了为什么「吞吐调优」和「延迟调优」经常给出相反的参数建议。
参数默认要点
--enable-prefix-cachingV1 默认开启基于块哈希复用前缀 KV。只缓存完整块,所以 --block-size 越小,命中粒度越细。多轮对话、Agent 场景收益最大。
--prefix-caching-hash-algosha256要跨机器/跨语言复现哈希,用 sha256_cbor;追求速度用 xxhash(需装 xxhash)。
--scheduling-policyFCFS可选 priority,请求带整数 priority,KV 不足时抢占低优先级。适合「在线 + 离线混跑」。
--async-scheduling随版本让 CPU 调度与 GPU 计算重叠,减少 GPU 空转。大模型、长序列场景收益明显,通常与 chunked prefill 一起用。
--long-prefill-token-threshold—与 --prefill-schedule-interval 配合,控制 DP rank 之间长 prefill 的准入与切片。PD 分离场景常用 512 / 1024。

4.5 服务协议与解析器

2026 年的前沿模型几乎都自带推理模式与工具调用,解析器配错会导致「内容为空」或「工具调用变成纯文本」。

模型族tokenizer-modetool-call-parserreasoning-parser
DeepSeek-V4 / V4.1deepseek_v4deepseek_v4deepseek_v4
Qwen3.5 / 3.8autoqwen3_coderqwen3
GLM-5 / 5.3glm5_nextglm47 / glm47_moeglm47 / glm45
Kimi-K3kimi_k3kimi_k3kimi_k3
MiniMax-M3autominimax_m3minimax_m3
gpt-ossautoopenai(内置 harmony)
最小组装:带工具调用与推理
vllm serve zai-org/GLM-5-FP8 \
  --served-model-name glm-5 \
  --tokenizer-mode glm5_next \
  --enable-auto-tool-choice \
  --tool-call-parser glm47 \
  --reasoning-parser glm47 \
  --chat-template-content-format=string

4.6 投机解码

在低到中等 QPS、显存受限的场景下,投机解码是性价比最高的延迟优化。方法选型见下表。

方法低 QPS(延迟)高 QPS(吞吐)适用前提
MTP高收益中高收益目标模型自带 MTP 头(DeepSeek/GLM/Qwen3.5 都有)
DSpark高收益中高收益DeepSeek-V4 / Mistral-Large-4 的融合 checkpoint
EAGLE / EAGLE3高收益中高收益需要匹配的 draft 模型
Draft Model高收益中收益需单独的小模型,显存换延迟
N-gram低–中中收益零额外模型,代码/摘要类重复文本收益高
Suffix低–中中收益动态推测深度,无需 draft 模型
--speculative-config 常见写法
# MTP:使用 checkpoint 内置的多 token 预测头
--speculative-config '{"method":"mtp","num_speculative_tokens":3}'

# DSpark:DeepSeek-V4-0813 融合 checkpoint,K 为草稿长度
--speculative-config '{"method":"dspark","num_speculative_tokens":6,"draft_sample_method":"probabilistic","rejection_sample_method":"block"}'

# EAGLE3:需要显式指定 draft 模型
--speculative-config '{"method":"eagle3","model":"/models/eagle3-draft","num_speculative_tokens":3}'

# n-gram:无额外模型,适合重复性强的文本
--speculative-config '{"method":"ngram","num_speculative_tokens":5,"prompt_lookup_max":4}'
投机解码的三个陷阱

① 高并发下投机 token 会占用 KV,反而降低吞吐——K 值不是越大越好。② 改了 K 或 max-num-seqs,CUDA Graph 的捕获尺寸要跟着按 n×(K+1) 重算,否则会 OOM 或回退 eager。③ 用 draft_sample_method=probabilistic 时,采样参数会显著影响接受率,压测结果不能直接外推到生产。

05并行策略选型

本引擎的推理拓扑与 KV 存放

为便于阅读,下图使用小规模设备组解释机制,不代表旗舰模型能装入这些设备。

MoE 的专家组可跨 TP×DP。DP4/TP1 不意味着四份独立完整模型;共享专家策略依赖模型与后端。MLA 不套用 GQA 的 KV head 分片结论。

vLLM · A · Attention TP4 + routed TP4-tp 4示例:4 设备、8 个路由专家;GQA 有 8 个 KV head;无共享专家的模型省略左支路。同一请求 / 同一批 token设备 0 · Attn Layer权重 TP 切片 1/4KV heads 0–1(1/4)设备 1 · Attn Layer权重 TP 切片 2/4KV heads 2–3(1/4)设备 2 · Attn Layer权重 TP 切片 3/4KV heads 4–5(1/4)设备 3 · Attn Layer权重 TP 切片 4/4KV heads 6–7(1/4)共享专家 Shared Experts本图选取 TP4 权重切分所有 token 均进入此支路融合 / 其他放置方式另行核对路由专家 Routed Experts同一 token 的所选专家并行计算全部 E0–E7权重切片 1/4全部 E0–E7权重切片 2/4全部 E0–E7权重切片 3/4全部 E0–E7权重切片 4/4AllReduce:汇合权重切片结果共享输出 + 路由输出进入后续层;继续使用各模块的并行组
vLLM · A · Attention TP4 + routed TP4 · KV 已明确按 GQA 示例标注:TP4 每卡 2 个 KV head;attention-DP4 每卡保存自己请求的 KV。共享专家布局是图示前提,不是该引擎所有后端的默认承诺。
vLLM · B · Attention TP4 + routed EP4-tp 4 --enable-expert-parallel示例:4 设备、8 个路由专家;GQA 有 8 个 KV head;无共享专家的模型省略左支路。同一请求 / 同一批 token设备 0 · Attn Layer权重 TP 切片 1/4KV heads 0–1(1/4)设备 1 · Attn Layer权重 TP 切片 2/4KV heads 2–3(1/4)设备 2 · Attn Layer权重 TP 切片 3/4KV heads 4–5(1/4)设备 3 · Attn Layer权重 TP 切片 4/4KV heads 6–7(1/4)共享专家 Shared Experts本图选取 TP4 权重切分所有 token 均进入此支路融合 / 其他放置方式另行核对路由专家 Routed ExpertsAllToAll dispatchE0–E1完整专家权重E2–E3完整专家权重E4–E5完整专家权重E6–E7完整专家权重AllToAll combine共享输出 + 路由输出进入后续层;继续使用各模块的并行组
vLLM · B · Attention TP4 + routed EP4 · KV 已明确按 GQA 示例标注:TP4 每卡 2 个 KV head;attention-DP4 每卡保存自己请求的 KV。共享专家布局是图示前提,不是该引擎所有后端的默认承诺。
vLLM · C · attention-DP4 + routed TP4-tp 1 -dp 4示例:4 设备、8 个路由专家;GQA 有 8 个 KV head;无共享专家的模型省略左支路。不同请求 / 本地批次设备 0 · Attn Layer本地完整权重KV:请求 A 的完整历史设备 1 · Attn Layer本地完整权重KV:请求 B 的完整历史设备 2 · Attn Layer本地完整权重KV:请求 C 的完整历史设备 3 · Attn Layer本地完整权重KV:请求 D 的完整历史共享专家 Shared Experts本图选取本地完整副本所有 token 均进入此支路融合 / 其他放置方式另行核对路由专家 Routed ExpertsAllGather:汇集各 rank 的 token全部 E0–E7权重切片 1/4全部 E0–E7权重切片 2/4全部 E0–E7权重切片 3/4全部 E0–E7权重切片 4/4ReduceScatter:返回本地 token共享输出 + 路由输出进入后续层;继续使用各模块的并行组
vLLM · C · attention-DP4 + routed TP4 · KV 已明确按 GQA 示例标注:TP4 每卡 2 个 KV head;attention-DP4 每卡保存自己请求的 KV。共享专家布局是图示前提,不是该引擎所有后端的默认承诺。
vLLM · D · attention-DP4 + routed EP4-tp 1 -dp 4 --enable-expert-parallel示例:4 设备、8 个路由专家;GQA 有 8 个 KV head;无共享专家的模型省略左支路。不同请求 / 本地批次设备 0 · Attn Layer本地完整权重KV:请求 A 的完整历史设备 1 · Attn Layer本地完整权重KV:请求 B 的完整历史设备 2 · Attn Layer本地完整权重KV:请求 C 的完整历史设备 3 · Attn Layer本地完整权重KV:请求 D 的完整历史共享专家 Shared Experts本图选取本地完整副本所有 token 均进入此支路融合 / 其他放置方式另行核对路由专家 Routed ExpertsAllToAll dispatchE0–E1完整专家权重E2–E3完整专家权重E4–E5完整专家权重E6–E7完整专家权重AllToAll combine共享输出 + 路由输出进入后续层;继续使用各模块的并行组
vLLM · D · attention-DP4 + routed EP4 · KV 已明确按 GQA 示例标注:TP4 每卡 2 个 KV head;attention-DP4 每卡保存自己请求的 KV。共享专家布局是图示前提,不是该引擎所有后端的默认承诺。
vLLM · MLA KV:同样四设备,复制与分片对照方案 A:-tp 4 -dcp 1;方案 B:-tp 4 -dcp 4(需模型与后端支持)方案 A · TP4,DCP1同一个请求 X / 当前 query设备0ABCD保存 M设备1ABCD保存 M设备2ABCD保存 M设备3ABCD保存 M每设备都保存完整的 A+B+C+D;四设备合计 4MTP 不自动消除这份 MLA KV 复制方案 B · TP4 + DCP4同一个请求 X / 当前 query设备0A———保存 M/4设备1—B——保存 M/4设备2——C—保存 M/4设备3———D保存 M/4每设备只保存不同的 1/4 历史 KV;四设备合计 M分片后通过通信合并 Attention 结果示例 token 级交错:A={0,4,8,12};B={1,5,9,13}C={2,6,10,14};D={3,7,11,15}。实际可按 token 或块交错。M 仅指可被 DCP 分片的逻辑 KV;不含权重、工作区和不可分片状态。上下两方案使用同样四个设备,不是串行流程,也不是增加四个设备。
vLLM · MLA KV:同样四设备,复制与分片对照 · 上下是两种独立配置,每种都将设备0–3横向排列;颜色表示同一请求的历史 token 子集。上图每设备都存 A/B/C/D,下图每设备只存其中一份;空槽表示该设备不保存这份数据。在图示的复制 MLA KV 路径下,可分片部分的物理总量从 4M 降到 M,代价是额外的 query / 局部输出与 LSE 通信。不代表整个服务显存下降四倍,也不将此结论套用到已按 KV head 分片的 GQA。

官方依据:vLLM 并行与配置文档。图示策略存在不代表某个模型、精度、硬件组合已实测。

MoE 时代,选错拓扑比选错卡更伤。

四种基本切法

选型决策

模型能装进单卡? 否 是 MoE 模型? 否(稠密) TP = 卡数(单机) 跨机?加 PP = 节点数 是 DP + EP(TEP / DEP) 瓶颈是延迟还是吞吐? 延迟 TP 优先,小 max-num-seqs 加 MTP / DSpark 开 CUDA Graph 吞吐 DP 优先,大 max-num-seqs MoE 配合 EP + 大 batch 评估 deepep_high_throughput 长上下文 / 多会话:评估 DCP 或 KV 卸载 前提:权重、激活与必要的 KV Cache 均满足显存约束。
图 6. 并行选型决策。注意第一层的判断对象是权重而非参数量——同样 397B,FP8 只要 4 卡 B300,BF16 就要 8 卡 H200。

EP 的两个反直觉细节

  1. EP 规模不是你设的,是算出来的。EP_SIZE = TP × DP。想开 8 路 EP 但只想用 4 张卡,做不到——必须 -dp 8 -tp 1 或 -dp 4 -tp 2。
  2. TP=1 时注意力层不通信。开启 EP 后,若 TP=1,注意力权重在每个 DP rank 上完整复制,各 rank 独立处理自己的请求,完全不需要 all-reduce。这正是 DEP(DP + EP)成为 MoE 默认拓扑的原因:把唯一强制的全局通信(注意力 all-reduce)消掉了。
对比:TP8 与 DP8+EP 的拓扑差异
# A. 纯 TP8 —— 所有层都切,每层两次 all-reduce
vllm serve deepseek-ai/DeepSeek-V4-Pro \
  --tensor-parallel-size 8

# B. DP8 + EP —— 注意力复制、专家分片,只有 MoE 层 all-to-all
vllm serve deepseek-ai/DeepSeek-V4-Pro \
  --data-parallel-size 8 \
  --enable-expert-parallel \
  --all2all-backend deepep_low_latency
官方实测结论

Kimi-K3 在单台 B300 上,TP8 + EP(注意力 TP8、专家走 MegaMoE 的 EP)相比纯 TP8,34 万 token 的单条 prompt 预填充从约 15 秒降到约 10 秒。而 DCP8(decode 上下文并行)能把 KV 容量从 260 万 token 提到 1850 万 token,代价是 decode 步骤慢 7–25%——这是「容量换速度」的典型权衡。

06逐模型实战配置

所有命令均来自官方 Recipes 验证过的配置,只做注释与必要的路径替换。

6.1 入门基线:gpt-oss-120b

最适合用来验证环境。117B 总参 / 5.1B 激活,原生 MXFP4,单张 80GB 卡即可跑,96 GB 显存起步。

bash · 单卡 / 多卡
# 单卡(A100 80G / H100 / H200 / B200 均可)
vllm serve openai/gpt-oss-120b

# TP4(多卡分摊,降低单卡显存压力)
vllm serve openai/gpt-oss-120b --tensor-parallel-size 4

# 启用工具调用(OpenAI harmony 格式)
vllm serve openai/gpt-oss-120b \
  --tool-call-parser openai \
  --enable-auto-tool-choice

# Blackwell 上 FlashInfer TRTLLM MXFP4 MoE 会自动选中;
# 如需显式固定:
vllm serve openai/gpt-oss-120b \
  --moe-backend flashinfer_trtllm \
  --quantization-config.moe.activation mxfp8

验证:

python
# Official OpenAI SDK works unchanged against vLLM
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="EMPTY")
r = client.chat.completions.create(
    model="openai/gpt-oss-120b",
    messages=[
        {"role": "system", "content": "Reasoning: high"},
        {"role": "user", "content": "Explain why eigenvalues matter."},
    ],
)
print(r.choices[0].message.content)

6.2 主力中坚:Qwen3.5-397B-A17B

397B 总参 / 17B 激活,GDN + 每 4 层全注意力,原生多模态。官方推荐 FP8 checkpoint。

精度权重显存最少卡数说明
BF16~800 GBH200 × 8 / B300 × 4H100 80G 需 TP16(2 节点)
FP8~400 GBH200 × 4 / B300 × 2官方推荐,2 卡 B300 即可
NVFP4~238 GBGB200 × 4Blackwell 专用
MXFP4 (AMD)~239 GBMI350X/MI355X × 1单卡 288 GB 可装
bash · 吞吐优先(文本)
# 8×H200:DP8 + EP,跳过视觉编码器,把显存全给 KV
vllm serve Qwen/Qwen3.5-397B-A17B-FP8 \
  -dp 8 \
  --enable-expert-parallel \
  --language-model-only \
  --reasoning-parser qwen3 \
  --enable-prefix-caching
bash · 多模态吞吐
vllm serve Qwen/Qwen3.5-397B-A17B-FP8 \
  -dp 8 \
  --enable-expert-parallel \
  --mm-encoder-tp-mode data \
  --mm-processor-cache-type shm \
  --reasoning-parser qwen3 \
  --enable-prefix-caching

# 加工具调用
# --enable-auto-tool-choice --tool-call-parser qwen3_coder
bash · 低延迟(MTP-1)
# 注意:MTP 会占用 KV,高并发下反而降吞吐
vllm serve Qwen/Qwen3.5-397B-A17B-FP8 \
  --tensor-parallel-size 8 \
  --speculative-config '{"method":"mtp","num_speculative_tokens":1}' \
  --reasoning-parser qwen3
Qwen3.5 的两个已知坑

① 单卡 MXFP4 场景下,默认 max_num_seqs=1024 会超过单卡留下的约 296 个 Mamba cache block,服务直接拒绝启动——必须显式 --max-num-seqs 64。② CUDA graph 捕获尺寸大于 Mamba cache 时会报 assert num_cache_lines >= batch,把 --max-cudagraph-capture-size 调小(默认 512)。

6.3 旗舰:DeepSeek-V4-Pro

1.6T 总参 / 49B 激活,权重约 960 GB(FP4+FP8 混合)。单机 8 卡装不下 GB200 一个 tray,需要 2 个 tray。

Checkpoint草稿模块备注
DeepSeek-V4-Pro-0813(默认)DSpark官方正式版,Agent 能力显著强于预览版
DeepSeek-V4-ProMTP预览版 FP4+FP8 混合权重
nvidia/DeepSeek-V4-Pro-NVFP4MTPmodelopt 重量化,Blackwell 专用
DeepSeek-V4-Pro-DSparkDSpark预览权重 + 融合 DSpark 模块
bash · H200 8 卡(DP8 + EP)
# H200 上 1M 上下文放不下全部 KV,官方建议封顶 800K
vllm serve deepseek-ai/DeepSeek-V4-Pro-0813 \
  --data-parallel-size 8 \
  --enable-expert-parallel \
  --max-model-len 800000 \
  --kv-cache-dtype fp8 \
  --block-size 256 \
  --tokenizer-mode deepseek_v4 \
  --reasoning-parser deepseek_v4 \
  --tool-call-parser deepseek_v4 \
  --enable-auto-tool-choice \
  --trust-remote-code
bash · GB200/GB300 双 tray(DEP8 + DSpark)
# 每个 4-GPU tray 起本地 4 个 DP rank,两 tray 合成 DP8
export VLLM_USE_V2_MODEL_RUNNER=1
export VLLM_DSV4_MEGA_FP8_COMBINE=1

vllm serve /models/DeepSeek-V4-Pro-0813 \
  --data-parallel-size 8 \
  --data-parallel-size-local 4 \
  --data-parallel-start-rank $((4 * NODE_RANK)) \
  --data-parallel-rpc-port 13345 \
  --data-parallel-hybrid-lb \
  --enable-expert-parallel \
  --enable-ep-weight-filter \
  --enable-cumem-allocator \
  --moe-backend deep_gemm_amxf4_mega_moe \
  --numa-bind --numa-bind-nodes 0 0 1 1 \
  --tokenizer-mode deepseek_v4 \
  --trust-remote-code \
  --max-model-len 1048576 \
  --kv-cache-dtype fp8 \
  --block-size 256 \
  --no-disable-hybrid-kv-cache-manager \
  --disable-flashinfer-autotune \
  --attention-config '{"backend":"FLASHINFER_MLA_SPARSE_DSV4","use_prefill_query_quantization":true,"indexer_kv_dtype":"mxfp4"}' \
  --speculative-config '{"method":"dspark","num_speculative_tokens":5,"draft_sample_method":"probabilistic","rejection_sample_method":"block"}'
为什么 H200 要封顶 800K

H200 是 141 GB × 8 = 1128 GB。960 GB 的混合精度权重在 DP 下每个 rank 都要一份非专家权重,KV 空间被挤到极限。官方 recipe 明确写了这条上限,并用 --max-model-len 800000 保留 KV 余量。H20 更紧,需要 --max-model-len 200000 --max-num-seqs 16。

6.4 超大 MoE:Kimi-K3 / K3.1-Pro

2.8T 参数,896 个路由专家每 token 激活 16 个(外加共享专家)。架构是 KDA 线性注意力 + 稀疏 MLA:93 层解码器中大部分是 Kimi Delta Attention(常数循环状态),每 4 层一次全 MLA。

版本总参激活上下文精度最小显存vLLM
Kimi-K32.8T16 / 8961,048,576MXFP4多节点≥0.33
Kimi-K3.1-Pro2.8T16 / 8961,048,576MXFP41,874 GB≥0.34
K3.1-Pro 只能走 day-0 镜像

它要求 vLLM ≥ 0.34.0,而当前稳定版是 0.33.0。官方 recipe 明确写了 install.pip: false——没有可用的 wheel,只能用 vllm/vllm-openai:kimi-k31 镜像(NVIDIA 侧是 CUDA 13 构建,AMD 侧是 ROCm 10)。

bash · K3.1-Pro,TP8 单机/双 tray
# 2 个 GB300 tray 或 1 台 B300 节点,TP8 基础布局
docker run --gpus all --ipc=host --shm-size 32g \
  -p 8000:8000 \
  -v ~/.cache/huggingface:/root/.cache/huggingface \
  vllm/vllm-openai:kimi-k31 \
  moonshotai/Kimi-K3.1-Pro \
  --tensor-parallel-size 8 \
  --trust-remote-code \
  --max-model-len 1048576 \
  --gpu-memory-utilization 0.85 \
  --enable-prefix-caching \
  --tool-call-parser kimi_k3 \
  --reasoning-parser kimi_k3 \
  --enable-auto-tool-choice
bash · K3 高并发(DCP8,KV 切到 8 卡)
# Decode Context Parallelism:MLA 潜变量与索引器 KV 分片,
# KV 容量约为 TP8 的 7 倍(约 18.5M vs 2.6M token),代价是 decode 慢 7–25%
vllm serve moonshotai/Kimi-K3 \
  --tensor-parallel-size 8 \
  --decode-context-parallel-size 8 \
  --dcp-comm-backend a2a \
  --attention-backend TOKENSPEED_MLA \
  --kv-cache-dtype fp8 \
  --mamba-ssm-cache-dtype bfloat16 \
  --enable-prefix-caching --prefix-match-unit 128 \
  --max-model-len 1048576 \
  --gpu-memory-utilization 0.88 \
  --speculative-config '{"model":"Inferact/Kimi-K3-DSpark","method":"dspark","num_speculative_tokens":6,"attention_backend":"TOKENSPEED_MLA","draft_sample_method":"probabilistic"}' \
  --tool-call-parser kimi_k3 --reasoning-parser kimi_k3 \
  --language-model-only
布局适用关键参数代价
TP8基线,最简单--tensor-parallel-size 8KV 容量最小
TP8 + EP长 prompt 的 TTFTMegaMoE 内核34 万 token 预填充 15s → 10s
TP8 + DCP8超长上下文、多会话--decode-context-parallel-size 8decode 慢 7–25%
TP8×PP2 + DCP84 tray 全量部署--pipeline-parallel-size 2流水气泡
KDA 状态池不在分页 KV 里

每个 KDA 层为每条序列保留常数大小的循环状态。这部分显存独立于 KV 池,会随并发数线性增长。所以 Kimi-K3 的 --max-num-seqs 要留余量,--gpu-memory-utilization 不宜压到 0.95。

6.5 Qwen3.8-Flash-Next

Qwen4 架构预览:125B 主模型 + 51B N-gram embedding,每 token 激活 6B。GDN + GQA 交替,原生多模态,262K 上下文。

精度checkpoint最小显存推荐布局
NVFP4Inferact/Qwen3.8-Flash-Next-NVFP4130 GB单 GB200 / GB300
FP8Qwen/Qwen3.8-Flash-Next-FP8250 GBTEP4(B300)/ TEP8(H200)
MXFP4amd/Qwen3.8-Flash-Next-Quark-MXFP4219 GBMI355X
BF16Qwen/Qwen3.8-Flash-Next423 GB8×H200
bash · B300 满 tray(TEP4,官方推荐)
vllm serve Qwen/Qwen3.8-Flash-Next-FP8 \
  --tensor-parallel-size 4 \
  --enable-expert-parallel \
  --gpu-memory-utilization 0.90 \
  --max-num-seqs 256 \
  --enable-prefix-caching \
  --kv-cache-dtype fp8 \
  --attention-config.indexer_kv_dtype fp8 \
  --speculative-config '{"method":"mtp","num_speculative_tokens":3}' \
  --enable-auto-tool-choice \
  --tool-call-parser qwen3_coder \
  --reasoning-parser qwen3
bash · 8×H200(TEP8 + Triton MoE)
# Hopper 上必须用 Triton MoE 后端
vllm serve Qwen/Qwen3.8-Flash-Next-FP8 \
  --tensor-parallel-size 8 \
  --enable-expert-parallel \
  --moe-backend triton \
  --gpu-memory-utilization 0.85 \
  --max-num-seqs 256 \
  --enable-prefix-caching \
  --kv-cache-dtype fp8 \
  --attention-config.indexer_kv_dtype fp8 \
  --speculative-config '{"method":"mtp","num_speculative_tokens":3}' \
  --enable-auto-tool-choice \
  --tool-call-parser qwen3_coder \
  --reasoning-parser qwen3
三个必须记住的约束

① 纯 TP8 与 FP8 checkpoint 不兼容——FP8 的 128 宽量化块无法被普通 TP 切分,必须开 --enable-expert-parallel。② --max-num-seqs 256 不要降——低于这个值会在启动时触发 Mamba cache 容量错误。③ 压测 MTP 要用 SPEED-Bench(--dataset-name speed_bench),随机数据集测不出真实接受率。

6.6 GLM-5 / 5.3

744B 总参 / 40B 激活,MLA + DSA。FP8 权重 893 GB,8×H200 单机可跑。

bash · 8×H200,MTP-3
vllm serve zai-org/GLM-5-FP8 \
  --tensor-parallel-size 8 \
  --speculative-config.method mtp \
  --speculative-config.num_speculative_tokens 3 \
  --tool-call-parser glm47 \
  --reasoning-parser glm47 \
  --enable-auto-tool-choice \
  --chat-template-content-format=string \
  --served-model-name glm-5-fp8
GLM-5.3 的推理控制变了

GLM-5.2 及之前用 chat_template_kwargs: {"enable_thinking": false} 关闭思考。GLM-5.3 无法关闭思考,改为 reasoning_effort(low/high/max,默认 max),另有 clear_thinking 控制多轮是否保留历史推理。客户端需要相应改造。

6.7 其余三个快速配置

模型最小显存关键启动参数
MiniMax-M3
427B / 26B,MSA 稀疏,原生多模态
1025 / 513 / 257 --trust-remote-code --reasoning-parser minimax_m3 --tool-call-parser minimax_m3
NVFP4 变体需 Blackwell;官方镜像 vllm/vllm-openai:minimax-m3
DeepSeek-V4.1-Flash
552B,8B/16B 激活,视觉语言
614 --tokenizer-mode deepseek_v41 --reasoning-parser deepseek_v41 --tool-call-parser deepseek_v41
最省事的旗舰级选择:单机 8×H200 即可,显存仅为 Pro 的 64%
ERNIE-5.5-Flash
280B / 14B,HCA + MLA-DSA
347 / 688 uv pip install vllm==0.32.0 + uv pip install git+https://github.com/baidu/vLLM-ERNIE.git
插件锁定 0.32.0,不能升版本;仅 NVIDIA

6.8 接入 Claude Code(本地模型跑 Agent)

vLLM 实现了 Anthropic Messages API,可以直接把 Claude Code 指向本地服务。要求模型有强工具调用能力。

bash
# 1) 起一个带工具调用的服务
vllm serve openai/gpt-oss-120b \
  --served-model-name my-model \
  --enable-auto-tool-choice \
  --tool-call-parser openai

# 2) 指向它启动 Claude Code
ANTHROPIC_BASE_URL=http://localhost:8000 \
ANTHROPIC_API_KEY=dummy \
ANTHROPIC_AUTH_TOKEN=dummy \
ANTHROPIC_DEFAULT_OPUS_MODEL=my-model \
ANTHROPIC_DEFAULT_SONNET_MODEL=my-model \
ANTHROPIC_DEFAULT_HAIKU_MODEL=my-model \
claude
三个必踩的坑

① --served-model-name 不能含 /,否则 Claude Code 无法识别。② Claude Code 会在 system prompt 里注入 per-request hash,直接摧毁前缀缓存——vLLM >0.17.1 已自动处理,旧版本需设 CLAUDE_CODE_ATTRIBUTION_HEADER=0。③ WebSearch 依赖 Anthropic 服务端工具,vLLM 会返回 400,需改用 MCP 的搜索服务。

07调优方法论

先测量,再调参。没有基线的调优就是赌博。

先定义四个指标

指标定义主要由什么决定
TTFT请求到首 token 的时间排队时长 + prefill 计算 + 首 token 采样。长 prompt 场景几乎全由 prefill 决定。
ITL / TPOT相邻 token 间隔decode 单步耗时。几乎只受 batch 内并发数和 KV 带宽影响。
Throughput每秒总 token(输入+输出)GPU 利用率 × batch 效率。
Goodput满足 SLO 的有效吞吐真正的业务指标;前三个都是它的分解。
官方建议

vLLM 官方明确说:vllm bench serve 主要用于功能验证和回归测试;生产压测推荐 GuideLLM,它在数据集加载、请求格式、负载模式上更灵活,且能自动生成报告。

三个旋钮的相互作用

调优不是单参数扫描,而是三维空间里找 Pareto 前沿。下表是方向性结论(不是绝对值):

旋钮↑ 调大↓ 调小副作用
max-num-batched-tokens TTFT ↓,吞吐 ↑ITL ↓,延迟更稳 过大时 decode 被长 prefill 拖住,尾延迟恶化
max-num-seqs 吞吐 ↑,GPU 利用率 ↑ITL ↓,单请求更快 过大时 KV 紧张,触发抢占重算
gpu-memory-utilization KV 容量 ↑,并发 ↑更安全,留给激活更多 过高时长 prompt 直接 OOM

按场景的配方

场景关键配置理由
低延迟对话
单用户、短输出
--max-num-batched-tokens 2048
--max-num-seqs 8
--speculative-config {"method":"mtp","num_speculative_tokens":1}
小预算让 decode 不被打断;小 batch 降低 ITL;MTP-1 接受率最高
高吞吐批处理
离线、延迟不敏感
--max-num-batched-tokens 16384
--max-num-seqs 512
--gpu-memory-utilization 0.95
大预算吃满 prefill;大 batch 摊薄权重读取;不浪费一点显存
长上下文 / RAG --max-model-len 1000000
--kv-cache-dtype fp8
--enable-prefix-caching
--block-size 64
KV 减半;前缀复用避免重复 prefill;小块提升命中粒度
多轮 Agent --enable-prefix-caching
-dcp 8(长会话)
KV 卸载到 host DRAM
每轮只新增少量 token,前缀命中率决定成本;DCP 提升会话容量
在线混合负载 --scheduling-policy priority
--async-scheduling
让交互请求优先;异步调度填补 GPU 空转

启动时间优化

大模型冷启动可能长达 10–20 分钟。三个手段可以叠加:

  1. 复用编译缓存。torch.compile 产物存在 VLLM_CACHE_ROOT(默认 ~/.cache/vllm),可以打包进镜像或跨机复制。设 VLLM_FORCE_AOT_LOAD=1 让缓存未命中时直接报错,而不是静默重编。
  2. 跳过显存测量。把上次日志里的 --kv-cache-memory 值传回去。
  3. 预编译内核。vllm download-kernels 把 Hopper 及更新架构上启动时才编译的内核提前装好,省几分钟。
优化等级行为用途
-O0无编译、无 graph、无 fusion调试、快速迭代
-O1简单编译 + 快速 fusion + PIECEWISE graph开发环境平衡点
-O2(默认)额外编译范围 + 更多 fusion + FULL_AND_PIECEWISE生产环境
-O3当前等同 -O2预留

压测命令

bash · vllm bench serve
vllm bench serve \
  --model zai-org/GLM-5-FP8 \
  --dataset-name random \
  --random-input 8000 \
  --random-output 1024 \
  --request-rate 10 \
  --num-prompts 32 \
  --ignore-eos
关于 MTP 压测的失真

官方提示:纯压测场景下 MTP 的接受率往往偏低,测出的吞吐会低估真实表现。因为压测用随机 prompt,而线上是结构化的真实文本。评估投机解码收益时,最好用生产流量回放。

08生产化与排错

把服务跑起来只是开始,能定位问题才算部署完成。

8.1 容器化

bash · 推荐写法
docker run --runtime nvidia --gpus all \
  -v ~/.cache/huggingface:/root/.cache/huggingface \
  -e HF_TOKEN=$HF_TOKEN \
  -p 8000:8000 \
  --ipc=host \
  vllm/vllm-openai:latest \
  --model Qwen/Qwen3-0.6B

# 老驱动(数据中心卡)可开启 CUDA 兼容层
-e VLLM_ENABLE_CUDA_COMPATIBILITY=1
  • --ipc=host 或 --shm-size 必须给:vLLM 用共享内存做 TP 进程间通信。
  • 可选依赖(如 audio)不在镜像里,需要基于官方镜像加一层 uv pip install --system "vllm[audio]==<同版本>"。
  • 镜像 tag 直接写版本号,不要用 latest 上生产。

8.2 监控指标

vLLM 在 /metrics 暴露 Prometheus 格式指标。以下是值得设告警的几个:

指标类型怎么看
vllm:kv_cache_usage_percGauge1.0 表示打满。长期 >0.95 说明该扩卡或降上下文
vllm:num_requests_waitingGauge持续增长 = 排队堆积,TTFT 会崩
vllm:num_preemptionsCounter抢占计数是最直接的显存不足信号,非零就该介入
vllm:prefix_cache_hits / queriesCounter比值即命中率。多轮场景低于 30% 说明缓存没生效
vllm:time_to_first_token_secondsHistogram看 p95/p99,不要只看均值
vllm:inter_token_latency_secondsHistogramITL 抖动通常来自 batch 波动或抢占
vllm:prompt_tokens_cached_by_sourceCounter按 device/host/disk/p2p 分层,定位缓存到底命在哪一层
bash · 快速查看
curl -s http://localhost:8000/metrics | grep -E 'kv_cache_usage|num_requests_waiting|num_preemptions|prefix_cache'

8.3 故障排查对照表

现象最可能原因处理
启动 OOM 权重 + 激活超出 gpu-memory-utilization 降 --max-model-len / --max-num-seqs;换低精度 checkpoint;开 --kv-cache-dtype fp8
运行中频繁 preempted 警告 KV 空间不足,请求被抢占重算 提高 --gpu-memory-utilization;降 --max-num-seqs 或 --max-num-batched-tokens;加 TP/PP
GPU 利用率上不去 CPU 核数不足,Engine Core 被抢占 按 2+N 分配物理核;检查是否有其他进程抢 CPU
首 token 很慢,后续正常 长 prefill 由于预算太小被切成很多块 提高 --max-num-batched-tokens;考虑 PD 分离
工具调用不生效 缺 --enable-auto-tool-choice 或 parser 不匹配 按 4.5 表格选 parser;确认 --tokenizer-mode 正确
推理内容为空 / 混在 content 里 reasoning parser 未配置或选错 补 --reasoning-parser;GLM-5.3 需改用 reasoning_effort
生成质量突然变差 0.8.0 起默认采样参数改为模型自带的 generation_config.json 试 --generation-config vllm 对比;若是则建议模型方修正 config
下载/加载卡住 网络或共享文件系统慢 先 hf download 到本地;用 --load-format dummy 跳过权重验证瓶颈位置
多机启动超时 大模型权重加载超过默认 600 秒 设 VLLM_ENGINE_READY_TIMEOUT_S=3600

8.4 安全要点

  • 默认无鉴权。对外暴露前必须加 --api-key 或放在网关后面。
  • 多模态 URL 是 SSRF 入口。用 --allowed-media-domains 限制域名,用 --allowed-local-media-path 限定可读目录(默认关闭)。
  • --trust-remote-code 会执行模型仓库里的 Python。只对可信来源开启,必要时先审计。
  • 多租户场景用 --prefix-caching-hash-algo sha256_cbor 并配合 cache salt,避免跨租户前缀泄露。

09附录:速查与来源

A. 参数速查

参数一句话
--max-model-lenprompt+output 总长度上限,解决 OOM 的第一手段
--gpu-memory-utilization本实例允许占用的显存比例,反推 KV 容量
--kv-cache-memory-bytes直接钉死 KV 字节数,覆盖上一条
--max-num-batched-tokens单步 token 预算,TTFT 与 ITL 的总开关
--max-num-seqs单步最大序列数,决定 CUDA Graph 规模
--kv-cache-dtypeKV 精度,fp8 通常必开
--block-sizeKV 块大小,影响前缀命中粒度
--enable-expert-parallelMoE 走 EP,规模 = TP × DP
-dp / -tp / -pp / -dcp数据 / 张量 / 流水 / 解码上下文并行
--all2all-backendEP 通信后端,prefill/decode 各有最优解
--speculative-config投机解码,JSON 形式
--tokenizer-mode新模型的渲染器,配错则工具调用全废
-O0…-O3优化等级,生产用默认 -O2

B. 常用环境变量

变量作用
VLLM_USE_MODELSCOPE从 ModelScope 而非 HF 拉模型
VLLM_CACHE_ROOT编译缓存目录,可打包进镜像
VLLM_FORCE_AOT_LOAD缓存未命中时直接报错,避免静默重编
VLLM_ENGINE_READY_TIMEOUT_S大模型加载等待上限,默认 600 秒
VLLM_ALLOW_LONG_MAX_MODEL_LEN允许超过 config 里的最大长度(需配合 --max-model-len)
VLLM_USE_FASTOKENS启用 Rust 分词后端,长前缀场景更快
VLLM_ROCM_USE_AITERAMD 上启用 AITER 内核,几乎必开
VLLM_WORKER_MULTIPROC_METHODfork / spawn,影响 NUMA 自动绑定是否生效
VLLM_HOST_IP多机场景下每节点必须不同

C. 来源

来源用途
docs.vllm.ai/en/latest参数释义、优化指南、显存节省、并行部署、监控指标(页面更新 2026-10-30)
recipes.vllm.ai逐模型 YAML:最小显存、验证硬件、启动命令(更新至 2026-11-05)
pypi.org/project/vllm版本号与发布日期核验
各模型官方模型卡 / config.json参数规模、层数、注意力超参、上下文长度
口径说明

本文所有「最小显存」取自 recipes YAML 的 vram_minimum_gb,其定义为「checkpoint 体积 × 1.2 余量」,用于判断能不能加载,不是推荐生产配置。生产环境应在该值之上留出 KV 与激活的余量。