vLLM:原理、部署与调优¶
vLLM 不是模型,也不是训练框架。它是一个大模型推理与服务引擎:负责把模型权重加载到 CPU/GPU,接收多个请求,管理 KV Cache 和批处理,再通过 HTTP API 返回生成结果。
面试中可以先这样概括:
vLLM 的价值不是让模型变聪明,而是让同一份模型在多人并发调用时更有效地使用 GPU。它用连续批处理动态调度请求,用分页方式管理 KV Cache,减少显存碎片和无效预留,并提供 OpenAI 兼容 API、多卡并行、量化和监控能力。
一、一次推理发生了什么¶
用户请求
↓ Tokenizer
Prompt Token
↓ Prefill:并行处理输入,计算首个 token,并建立 KV Cache
↓ Decode:根据 KV Cache 逐个生成后续 token
返回文本 / JSON / 工具调用
Prefill 和 Decode 的区别¶
| 阶段 | 做什么 | 主要特征 | 影响指标 |
|---|---|---|---|
| Prefill | 一次处理输入 Prompt,建立 KV Cache | 计算密集;长 Prompt 更重 | 首 token 延迟 TTFT |
| Decode | 读取 KV Cache,逐 token 生成 | 内存带宽和调度更敏感 | token 间延迟 ITL、输出 tokens/s |
如果业务的 RAG 上下文很长,Prefill 会变重;如果回答很长或并发很多,Decode 和 KV Cache 压力会更明显。
二、vLLM 为什么吞吐高¶
Continuous Batching:请求动态进入批次¶
固定批处理必须等一批请求全部完成。不同用户的输出长度不一样,短请求结束后留下的计算位置会浪费。
连续批处理会在每次调度时重新组合仍在生成的请求和新请求:某个请求结束后,新请求可以进入,不必等待整批结束。因此高并发时 GPU 更不容易空转。
Paged KV Cache:像分页内存一样管理上下文缓存¶
KV Cache 保存每个请求已经计算过的注意力 Key/Value,避免每生成一个 token 都重新计算整个历史。它的代价是显存会随并发数 × 上下文长度增长。
vLLM 将 KV Cache 划分成块,按需要分配,而不是为每条请求预留一整块连续空间。可以把它理解为操作系统分页:
PagedAttention 是在这种分块 KV Cache 上执行注意力计算的机制。它优化的是显存管理和服务吞吐,不改变模型权重本身。
Prefix Caching:复用相同前缀¶
当多个请求共享相同系统提示、长文档前缀或固定模板时,前缀缓存可以复用已经计算的 KV Cache,减少重复 Prefill。它对完全不同的 Prompt 没有明显收益,还需要占用缓存空间。
Chunked Prefill:长输入分块调度¶
长 Prompt 的 Prefill 可能阻塞正在 Decode 的短请求。Chunked Prefill 将长输入拆成多段,与 Decode 请求共同调度,用 max-num-batched-tokens 控制每轮 token 预算。vLLM V1 会在模型支持时默认启用;仍应通过真实负载观察 TTFT 与 ITL,而不是照抄固定数值。官方调优说明
三、最小部署¶
下面示例只表示参数关系,模型名称、精度和上下文长度必须结合实际 GPU 验证:
vllm serve Qwen/Qwen2.5-7B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--served-model-name qwen-7b \
--dtype auto \
--gpu-memory-utilization 0.90 \
--max-model-len 8192 \
--max-num-seqs 64 \
--enable-prefix-caching
检查模型和接口:
curl http://127.0.0.1:8000/v1/models
curl http://127.0.0.1:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "qwen-7b",
"messages": [{"role": "user", "content": "解释什么是 KV Cache"}],
"temperature": 0.2,
"max_tokens": 300
}'
--api-key 不能代替完整的边界防护。官方文档明确说明,它只保护部分路径;生产服务仍应放在反向代理或 API Gateway 后,统一处理 TLS、认证、限流、审计和网络访问控制。OpenAI 兼容服务文档
四、核心参数怎么理解¶
1. 模型、长度与精度¶
| 参数 | 控制什么 | 调大/调整后的影响 |
|---|---|---|
vllm serve <模型名或目录> |
加载模型;本页采用位置参数写法 | 模型规模决定基础能力、权重显存和硬件要求 |
--served-model-name |
API 对外显示的模型名 | 便于应用使用稳定别名,不改变模型能力 |
--max-model-len |
单请求允许的最大总长度 | 越大,单请求可用上下文越长,但 KV Cache 容量压力越高,可并发数通常下降 |
--dtype |
权重与计算使用的数值类型 | auto 通常遵循模型配置;FP32 更占显存,FP16/BF16 更适合 GPU 推理 |
--quantization |
使用 AWQ、GPTQ、FP8 等量化实现 | 权重更小、模型更容易放入显存;速度和质量取决于格式、模型与硬件 |
--kv-cache-dtype |
KV Cache 的数值类型 | FP8 Cache 可减少上下文缓存显存,但需要做长上下文和任务质量回归 |
2. 显存与并发¶
| 参数 | 控制什么 | 常见取舍 |
|---|---|---|
--gpu-memory-utilization |
单实例用于权重、执行和 KV Cache 的目标显存比例 | 较高可留出更多 KV Cache,但过高会缺少峰值余量,或与其他进程争抢显存 |
--max-num-seqs |
一轮调度可处理的最大序列数 | 较高可能提升并发吞吐,也会增加 KV Cache 和调度压力;不是实际用户数 |
--max-num-batched-tokens |
一轮调度的 token 总预算 | 较大通常有利于 Prefill 吞吐/TTFT;较小更偏向保护 Decode 的 ITL |
--enable-prefix-caching |
是否复用相同 Prompt 前缀 | 固定系统提示、多轮公共前缀收益高;随机请求收益低 |
三者关系可以这样记:
它们设得越大,不代表服务一定越快。超过 GPU 和真实负载需要后,常见结果是显存紧张、请求被抢占、P95 延迟升高甚至 OOM。
3. 多 GPU 和扩展¶
| 参数/方式 | 解决的问题 | 注意事项 |
|---|---|---|
--tensor-parallel-size N |
把同一层计算拆到 N 张 GPU;单卡放不下模型 | 每层需要通信,优先使用节点内高速互联 |
--pipeline-parallel-size N |
把模型层划分成 N 个流水阶段 | 可跨节点,但存在阶段等待和通信开销 |
| 多个独立实例 + 负载均衡 | 一份模型已能放入单卡/一组卡,但吞吐或可用性不够 | 每个副本都加载完整权重,需要网关和健康检查 |
对于普通 Dense 模型,扩容并发通常是启动多个独立 vLLM 实例,而不是盲目设置数据并行参数。TP/PP 主要解决一份模型如何跨卡放置;多副本解决更多请求。官方示例见 Parallelism and Scaling。
五、“调整精度”到底调什么¶
面试中先反问或主动澄清:这里说的是数值精度、量化精度,还是回答准确率?
数值精度:FP32、FP16、BF16¶
| 类型 | 大致特点 | 常见判断 |
|---|---|---|
| FP32 | 每个权重占用更多内存,数值范围和精度高 | 推理通常没必要;显存和吞吐成本较高 |
| FP16 | 显存约为 FP32 的一半,GPU 支持广 | 数值范围小于 BF16,少数模型更容易溢出 |
| BF16 | 与 FP16 占用相近,指数范围接近 FP32 | 硬件支持时常作为现代大模型推理的稳妥选择 |
使用 --dtype auto 是合理起点。不要为了“更准”直接强制 FP32;多数模型的推理质量不会因此出现值得显存成本的提升,还必须看模型原始训练精度和硬件支持。
权重量化:FP8、INT8、INT4、AWQ、GPTQ¶
量化是用更少 bit 表示权重或激活。主要收益是减少显存,使更大的模型能够部署,部分硬件上也可能提高吞吐。代价可能是生成质量下降、量化/反量化开销增加,或某种格式没有适配当前 GPU 内核。
正确步骤是:
- 用 BF16/FP16 原模型建立质量和性能基线。
- 选择当前 GPU 明确支持的量化格式。
- 用同一套真实测试集比较回答正确率、格式遵循、长上下文、工具调用和 RAG。
- 同时记录显存、TTFT、ITL、吞吐和错误率。
- 质量和稳定性验收通过后再发布,并保留回滚版本。
vLLM 支持的量化实现及硬件兼容性会变化,应查部署版本的官方量化兼容表,不能只记“INT4 最省显存”。
KV Cache 量化¶
--kv-cache-dtype 调的是上下文缓存,不是模型权重。它更直接影响长上下文和高并发时的缓存容量。降低 KV Cache 精度后,应重点回归:长文档问答、长对话一致性、精确抽取和重复生成稳定性。
回答准确率:不是靠 dtype 参数解决¶
如果用户说“回答不准”,优先按下面顺序定位:
模型能力/版本是否适合任务
↓
聊天模板、System Prompt 是否正确
↓
输入是否超过长度限制,或被上游应用截断
↓
RAG 是否召回正确证据
↓
Temperature / Top-P 是否适合任务
↓
最后再比较量化造成的质量差异
事实问答和结构化抽取可从较低 temperature 开始;创作任务可以更高。但采样参数只能改变输出随机性,无法补回被截断的上下文,也无法修复错误的 RAG 召回。
max-model-len 是输入与输出合计的服务长度上限,通常超长请求会报错;不要把它理解成服务总会自动截断。还要检查应用是否主动截断历史、RAG 内容,以及请求的输出长度预算。
实际切换方式¶
下面是已有 vLLM 环境中的替代启动示例,各选项需匹配当前版本与 GPU。模型目录应提前准备好权重、配置和 Tokenizer;每次只启动其中一个进行对照。
# 基线:硬件支持 BF16,使用原始模型目录
vllm serve /data/models/base-model --dtype bfloat16 --max-model-len 4096
# 对照 FP16:仍使用同一原始模型
vllm serve /data/models/base-model --dtype half --max-model-len 4096
# AWQ:这里必须换成已经完成 AWQ 量化的兼容模型制品
vllm serve /data/models/model-awq --quantization awq --dtype half --max-model-len 4096
# FP8 KV Cache:保留权重精度,调整缓存精度;须确认后端与缩放因子支持
vllm serve /data/models/base-model --dtype bfloat16 --kv-cache-dtype fp8 --max-model-len 4096
--quantization awq 是加载方式,不能把任意原始权重即时变成 AWQ 制品;部分其他量化方法支持在线转换,需要按具体方法说明操作。FP8 Cache 的 scale 应按对应版本文档和模型制品配置,不能仅以“成功启动”判断精度正确。
FP32 每个权重约 4 字节,FP16/BF16 约 2 字节,INT8 约 1 字节,INT4 约半字节。以理想化 7B 参数模型计算,纯权重分别约为 28、14、7、3.5 GB(十进制)。实际还需量化元数据、KV Cache、激活和运行时工作区,所以 14 GB 权重不代表 16 GB GPU 就一定足够。
六、调优顺序¶
先定义指标¶
| 指标 | 说明 |
|---|---|
| TTFT | 从请求进入到第一个 token 返回;用户最直观的“开始回答速度” |
| ITL | 相邻输出 token 的间隔;决定回答是否顺滑 |
| 吞吐 | 每秒处理的请求数或 token 数 |
| P95/P99 | 高分位延迟;比平均值更能反映拥塞 |
| KV Cache 使用率/抢占 | 判断上下文与并发是否超过缓存容量 |
| 质量通过率 | 固定测试集上回答、格式、工具调用和引用是否正确 |
推荐顺序¶
- 固定模型、GPU、数据集和请求长度分布,建立基线。
- 将
max-model-len收紧到业务真正需要的长度。 - 逐步增加并发压测,观察吞吐、TTFT、ITL 和 P95。
- 调整
max-num-seqs;再用max-num-batched-tokens平衡 Prefill 与 Decode。 - 有大量公共前缀时启用前缀缓存并观察命中率。
- 单卡放不下再做量化或 TP;吞吐不够则比较多副本和扩卡成本。
- 每次只改一类参数,同时做质量回归。
七、常见现象¶
| 现象 | 优先检查 |
|---|---|
| 启动时 OOM | 模型大小和 dtype、量化格式、GPU 是否被占用、max-model-len、显存比例 |
| 能启动但并发很低 | KV Cache 容量、上下文长度、max-num-seqs、模型权重占用 |
| TTFT 很高 | Prompt 太长、排队、Prefill token 预算、CPU Tokenizer、模型未预热 |
| 输出时断时续 | Decode 排队、过大的 Prefill 批次、GPU 抢占、网络反向代理缓冲 |
| GPU 利用率低 | 并发不足、输出过短、CPU/网络瓶颈、模型过小或批处理不足 |
| 量化后反而慢 | 当前 GPU/量化格式缺少高效内核,反量化开销抵消收益 |
| 回答质量下降 | 模型/量化版本、聊天模板、采样参数、上下文截断、RAG 召回 |
| 多卡性能不升反降 | 卡间互联、TP 通信、NUMA、容器 GPU 拓扑和批量不足 |
八、面试回答模板¶
vLLM 是面向在线大模型推理的服务引擎。一次生成分 Prefill 和 Decode:Prefill 处理输入并建立 KV Cache,Decode 根据缓存逐 token 生成。vLLM 通过 Continuous Batching 动态合并并发请求,用分页方式管理 KV Cache,减少显存碎片,所以重点优势是高并发吞吐。调参时我会先看
max-model-len、gpu-memory-utilization、max-num-seqs和max-num-batched-tokens,再根据模型是否放得下选择量化、Tensor Parallel 或多副本。所谓调整精度要区分 dtype、权重量化、KV Cache 精度和回答准确率;回答不准不能简单靠改 FP16/FP32 解决,必须同时检查模型、模板、上下文截断、RAG 和采样参数。
参数随 vLLM 版本变化,部署前应使用 vllm serve --help=<参数名> 核对当前版本;完整参考见 vLLM Serve CLI。