深色模式
vLLM 部署与 PagedAttention
摘要:本文面向要把 LLM 跑上生产的工程师。先讲清 vLLM 的核心创新 PagedAttention(把操作系统的虚拟内存分页思想引入 KV Cache),再给出从单机到多卡、从 fp16 到 FP8 量化的完整部署命令,最后覆盖验证、回滚、故障排查与安全。适用版本:vLLM 0.8.x–0.9.x 区间(PyPI 同时期版本见 2026-10-09 检索结果),命令以官方文档为准,版本相关处已标注。
适用版本与前提
- vLLM:主线 0.8.x–0.9.x(镜像
vllm/vllm-openai:latest跟随最新;生产建议锁具体 tag) - 硬件:单卡 ≥24GB(如 4090)可跑 7B/8B fp16;A100/H100 80GB 可跑 70B(TP=2 或量化)
- 依赖:NVIDIA 驱动、CUDA、Docker(推荐,避免环境差异)
版本与镜像
官方 Docker Hub 标签更新节奏与 PyPI wheel 不完全同步,部分新特性(如 Blackwell FP8)可能只在较新版镜像。latest 不等于稳定,生产请固定 tag 并记录 hash。
核心概念:PagedAttention 解决了什么
传统推理给每个请求预分配一段连续且按"最长可能序列"计算的 KV Cache。问题有三:
- 碎片:实际序列远短于预留长度,剩余空间无法给别的请求用。
- 内部碎片 + 复制浪费:多轮对话里相同前缀被反复复制。
- 预留即占用:为最坏情况预留,并发上不去。
PagedAttention 把 KV Cache 切成固定大小的块(block,如 16 个 token),逻辑上每个请求有一张"块表(block table)"映射到物理块,物理块可以不连续。这就像 OS 的虚拟内存分页:
收益:请求完成即释放物理块、立刻复用;无需为最坏长度预留;相同前缀可共享物理块(配合 prefix caching)。社区常见说法:把 GPU 利用率从传统 ~30–40% 拉到 ~85%+,吞吐对比原生 HF Transformers 2–4×——属相对值,具体数字随模型/硬件/流量而定,勿当 SLA。
架构与原理
调度器在每一步(step)决定:把哪些请求拼成当前 batch、给新请求分配哪些块、对显存不足的低优先请求做抢占(swap 到 CPU 或重算)。核心是"每一步都尽量把 GPU 喂满"。
连续批处理与分页是搭档
PagedAttention 提供"可随时增减、可复用"的显存;连续批处理(见 continuous-batching.md)提供"随时插入/移走请求"的调度。两者缺一,GPU 利用率都上不去。
生产部署
1. 单机单卡最简(7B/8B)
bash
# 拉取镜像(生产锁版本,如 :v0.9.x)
docker pull vllm/vllm-openai:latest
# 启动 OpenAI 兼容服务
docker run --gpus all --ipc=host -p 8000:8000 \
-v /mnt/models:/models \
vllm/vllm-openai:latest \
--model /models/Qwen2.5-7B-Instruct \
--served-model-name qwen2.5-7b \
--max-model-len 32768 \
--gpu-memory-utilization 0.90 \
--dtype half \
--tensor-parallel-size 1
# 说明:
# --ipc=host 共享宿主机 IPC,vLLM 分页/共享内存依赖它,省略可能报 shared memory 不足
# --max-model-len 上下文长度上限,决定 KV Cache 上限,设太大但请求短会浪费
# --gpu-memory-utilization 0.90 允许用 90% 显存给 KV 池;留 10% 给权重常驻与碎片
# [版本相关] 参数名与默认值随版本变化,以上为 0.8.x–0.9.x 区间写法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2. 多卡张量并行(70B 或超大上下文)
bash
# 70B fp16 约 140GB,单张 80GB 放不下,用 TP=2(需 2×80GB 或量化)
docker run --gpus all --ipc=host -p 8000:8000 \
-v /mnt/models:/models \
vllm/vllm-openai:latest \
--model /models/Qwen2.5-72B-Instruct \
--tensor-parallel-size 2 \
--max-model-len 16384 \
--gpu-memory-utilization 0.901
2
3
4
5
6
7
8
2
3
4
5
6
7
8
3. FP8 量化(省显存、提吞吐)
bash
# 使用已量化权重(如 RedHatAI 的 FP8 版本)或启用量化后端
docker run --gpus all --ipc=host -p 8000:8000 \
-v /mnt/models:/models \
vllm/vllm-openai:latest \
--model /models/Meta-Llama-3.1-8B-Instruct-FP8 \
--quantization fp8 \
--max-model-len 16384
# [版本相关] 量化方案(fp8 / awq / gptq / compressed-tensors)与开关名随版本演进,
# 请核对官方 quantization 文档;并非所有模型都有现成 FP8 权重。1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
4. 用 Python 高层 API 做离线批量
python
# 适合离线摘要/批量打分;vLLM 高层 LLM 类
from vllm import LLM, SamplingParams
llm = LLM(model="/models/Qwen2.5-7B-Instruct",
tensor_parallel_size=1,
gpu_memory_utilization=0.90,
max_model_len=32768)
params = SamplingParams(temperature=0.7, top_p=0.95, max_tokens=256)
outputs = llm.generate(
["总结以下文档:...", "给这段评论分类:..."], params)
for o in outputs:
print(o.prompt[:30], "->", o.outputs[0].text[:80])
# [版本相关] LLM / SamplingParams 构造参数以官方 API 参考为准1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
验证
bash
# 启日志关键行:确认 KV 池与并发估算
# INFO GPU KV cache size: 643,232 tokens
# INFO Maximum concurrency for 40,960 tokens per request: 15.70x
# 流式对话冒烟
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"qwen2.5-7b",
"messages":[{"role":"user","content":"写一段 100 字的文案"}],
"max_tokens":200,"stream":true}'1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
用 vLLM 自带指标做可观测
vLLM 暴露 Prometheus 指标(如 vllm:num_requests_running、vllm:gpu_cache_usage_sys)。接 Grafana 看 KV 利用率是否在 80% 附近、是否有大量抢占(preemption)发生——抢占多说明 --max-model-len/显存利用率需调或该加卡。
回滚与清理
升级回滚
vLLM 大版本可能改动调度、量化、API。升级前固定旧 tag,灰度切流;异常用 docker rm -f 删新容器、重启旧版。--volume /mnt/models 的宿主机目录切勿删除(那是权重,不是容器数据)。
故障排查
| 现象 | 可能原因 | 处理 |
|---|---|---|
RuntimeError: CUDA out of memory | 模型 + KV 超显存 | 降 --gpu-memory-utilization、加 TP、上量化、降 --max-model-len |
shared memory / IPC 报错 | 未加 --ipc=host | 容器加 --ipc=host |
| 吞吐低、GPU 利用率低 | batch 太小、并发不足 | 提高并发、调 --max-num-seqs、做压测(见 perf-tuning) |
大量 preempted 日志 | KV 池不够 | 降低并发上限或加显存/卡 |
no kernel image available (新卡) | 镜像 CUDA 架构不支持 | 换支持该架构的镜像/构建(如 Blackwell 需较新版)[版本相关/未实测] |
安全与合规
- 越权:
vllm serve默认无鉴权。务必放网关后,加 API Key / mTLS,禁止 8000 直连公网。 - 成本失控:恶意超长
max_tokens+ 高并发可刷爆 GPU。网关层强制:单请求max_tokens上限、输入长度上限、每用户并发/QPS 限制。 - 权重许可:Qwen/Llama 等受社区许可证约束,商用请确认许可范围。
成本与性能(示意)
- Qwen2.5-7B fp16 单卡 4090(24GB):权重 ~15GB,KV 池约 7–8GB,并发上限较低,适合开发/小流量。
- 同模型 A100 80GB:KV 池可到 ~60GB,按 7B 每请求 KV 约 0.5–1GB/4k tokens 估算可并发数十到上百(具体看长度)[未实测]。
- 量化(FP8/AWQ)可把权重显存近乎减半,把省下的显存全给 KV 池,吞吐与并发提升明显,精度损失通常可控但需按业务评测。