vLLM:基于 PagedAttention 的高吞吐推理引擎
什么是 vLLM?为什么需要它?
在大语言模型(LLM)的落地中,推理延迟和吞吐量是两大核心瓶颈。传统的推理方式逐个生成 token,造成 GPU 计算资源大量闲置,难以满足实时大批量服务的需求。vLLM 正是为解决这一问题而生的高性能推理引擎。它通过创新的 PagedAttention 注意力算法和精细的内存管理,将 LLM 推理吞吐量提升至极致,同时几乎不影响模型精度,已成为生产环境中部署开源模型的首选方案。
vLLM 的核心理念可用一句话概括:像操作系统管理虚拟内存一样管理 KV 缓存。
推理瓶颈:KV 缓存的内存浪费
在自回归生成中,每个 token 的注意力计算都依赖于所有先前 token 的 Key (K) 和 Value (V) 向量。为避免重复计算,推理框架会将它们缓存在 GPU 显存中,这便是 KV 缓存。
传统框架预分配一块连续显存作为 KV 缓存,长度等于模型最大上下文长度(如 4096 或 8192)。但实际请求的序列长度参差不齐,短请求也占用整段缓存,导致:
- 内部碎片:预留空间远大于实际需要。
- 外部碎片:不同请求分配与释放后,显存变得支离破碎,无法容纳新的大序列请求,即使剩余总显存充足。
此外,传统框架无法在请求之间共享相同前缀的 KV 缓存(如 few-shot 示例),造成重复计算和存储。vLLM 的 PagedAttention 正是针对这两大痛点设计。
PagedAttention 原理:分页管理 KV 缓存
PagedAttention 借鉴操作系统的虚拟内存分页机制,将每个请求的 KV 缓存切分为固定大小的 块(Block),每个块包含固定数量 token 的 K 和 V 张量。这些块可以非连续地存储在显存中,通过 块表(Block Table) 记录逻辑位置到物理地址的映射。
1. 近乎零内存浪费
- 块的大小固定(通常为 16 或 32 个 token),仅最后一个块可能存在小部分未使用空间,内存利用率极高。
- 动态分配块,请求需要多少就分配多少,完全消灭内部碎片和外部碎片。
2. 高效前缀共享
当多个请求使用相同的 system prompt 或 few-shot 示例时,其 KV 缓存块在物理上只存储一份,通过引用计数共享。新请求只需复制块表并增加引用计数,无需复制数据本身。这显著节省显存,加速并发请求的处理。
3. 灵活的内存调度
vLLM 的调度器可以在产生新 token 时动态增加块分配,逻辑足够简洁,允许实现精细的 抢占式调度 与 公平性策略,无需等待一个大连续内存块即可发起请求。
PagedAttention 的内核实现在 GPU 上高度优化,尽管增加了块表的访存间接开销,但通过融合算子与巧妙并行,整体计算效率与连续缓存方案持平或更优。
vLLM 核心优势与特性
- 极致吞吐量:相比传统 HuggingFace Transformers,同等硬件下吞吐可提升 20 - 30 倍,相比其他主流框架也有 2 - 4 倍优势。
- 首个实现 PagedAttention 的引擎,现已成为众多框架(如 TensorRT-LLM、SGLang)借鉴的范式。
- 无缝兼容 HuggingFace 模型:支持大多数基于 Transformer 的开源模型,包括 Llama 系列、Mistral、Qwen、ChatGLM、Falcon 等。
- 连续批处理(Continuous Batching):请求完成后立刻释放资源,新请求即时插入,避免批次等待,最大化 GPU 计算利用率。
- 量化支持:集成 AWQ、GPTQ、SqueezeLLM 等量化方法,可在相同硬件上运行更大模型或提升吞吐。
- 张量并行:支持多 GPU 分布式推理,通过张量并行轻松扩展更大模型。
- 流式输出与 OpenAI 兼容 API:原生支持 server 模式,提供兼容
/v1/completions和/v1/chat/completions的接口。
环境搭建与安装
首先确保有 CUDA 12.1 及以上环境(PyTorch 2.1+)。推荐使用 conda 创建干净环境:
conda create -n vllm python=3.10 -y
conda activate vllm
使用 pip 安装(推荐)
pip install vllm
此命令会安装预编译的 CUDA 二进制包。若需要特定 CUDA 版本或手动编译,可参考官方文档从源码安装:
git clone https://github.com/vllm-project/vllm.git
cd vllm
pip install -e .
快速上手:离线批量推理
最简单的使用方式是调用 vLLM 的 Python API 进行离线批量生成。以下是加载 Llama3-8B 模型并一次性生成多条回复的示例:
from vllm import LLM, SamplingParams
# 初始化 LLM 引擎,指定模型名称和 GPU 显存使用率
llm = LLM(model="meta-llama/Meta-Llama-3-8B-Instruct",
gpu_memory_utilization=0.9,
max_model_len=4096)
# 定义生成参数
sampling_params = SamplingParams(temperature=0.8, top_p=0.95, max_tokens=256)
# 输入 prompts 列表
prompts = [
"请用中文解释量子计算的基本原理。",
"写一首关于人工智能的七言绝句。"
]
# 批量生成
outputs = llm.generate(prompts, sampling_params)
for output in outputs:
prompt = output.prompt
generated_text = output.outputs[0].text
print(f"Prompt: {prompt}")
print(f"Generated: {generated_text}\n")
LLM 类会初始化推理引擎,自动管理 KV 缓存分页与调度。gpu_memory_utilization 参数控制预留多少显存给 KV 缓存,其余用于模型权重。max_model_len 限制最大上下文长度以适应显存。
启动 OpenAI 兼容 API 服务
vLLM 提供内置 HTTP 服务器,与 OpenAI API 协议兼容,可直接作为后端服务接入各类前端或框架(如 LangChain、LlamaIndex)。
启动服务
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Meta-Llama-3-8B-Instruct \
--gpu-memory-utilization 0.9 \
--max-model-len 8192 \
--port 8000
加载成功后,可用 curl 测试聊天补全接口:
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "meta-llama/Meta-Llama-3-8B-Instruct",
"messages": [
{"role": "user", "content": "你好!请介绍一下你自己。"}
],
"temperature": 0.7
}'
返回结构与 OpenAI 官方 API 一致,可直接将任何使用 OpenAI SDK 的代码的 base_url 指向 http://localhost:8000/v1。
高级配置与调优
1. 张量并行(多 GPU)
对于无法放入单卡显存的大模型,使用 tensor-parallel-size 切分权重:
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Meta-Llama-3-70B-Instruct \
--tensor-parallel-size 4
--tensor-parallel-size 等于所用 GPU 数量。vLLM 采用 Megatron-LM 风格张量并行,通信极高效。
2. 量化模型加速
加载 AWQ 或 GPTQ 量化模型可减少显存占用,提升吞吐。示例:
python -m vllm.entrypoints.openai.api_server \
--model TheBloke/Llama-2-7B-AWQ \
--quantization awq
此时模型权重仅占约原大小的 1/4,允许更大批次或更长上下文。
3. 调度策略与显存优化
--max-num-seqs:同时处理的最大请求数,限制并发防止 OOM。--max-num-batched-tokens:一次 forward 处理的 token 总数上限,微调可平衡延迟与吞吐。--enable-prefix-caching:开启自动前缀缓存,对具有共享前缀的请求自动复用 KV 缓存块,无需额外代码。建议总是启用。--swap-space:当显存不足时,可配置 CPU 交换空间(GiB),实现非阻塞式抢占。
4. 自定义采样与停止条件
SamplingParams 支持停止词设定、重复惩罚、频率惩罚等:
sampling_params = SamplingParams(
temperature=0.0,
max_tokens=100,
stop=["\n", "Human:"],
repetition_penalty=1.1
)
在 API 调用中可通过 stop 字段传入停止字符串列表。
应用场景与最佳实践
- 聊天机器人后端:利用前缀缓存加速多轮对话(缓存整个对话历史)。
- 批量资料处理:如批量摘要、翻译、信息提取,vLLM 离线批处理模式下单机可实现每秒数千 token 的处理速度。
- RAG 管道:在检索增强生成中,可将检索到的上下文作为共享前缀注入所有请求,大幅降低首 token 延迟。
- 多模型混合部署:可在不同端口或不同 GPU 上部署多个 vLLM 实例,通过负载均衡分发不同类型任务。
监控与调试:vLLM 输出性能统计日志,如每轮生成的吞吐、延迟分布。同时支持 Prometheus 指标,方便集成监控系统。
常见问题与解决
- 显存溢出(OOM):降低
gpu_memory_utilization或减小max_model_len;使用量化模型;减少max-num-seqs;开启 swap space。 - 首次推理慢:vLLM 需要在首次 forward 时编译 CUDA 图(CUDA Graphs),后续批次会大幅加速,这是正常现象。
- 模型不支持:查看官方支持列表,通常基于 Llama、Mistral、Falcon 架构的模型均受支持;自定义模型需实现 vLLM 的注册接口。
- 输出截断:检查
max_tokens设置,并确认stop参数未意外触发。
总结
vLLM 借助 PagedAttention 重塑了 LLM 推理的内存管理,几乎消除了 KV 缓存浪费,并原生支持显存共享与动态批处理,实现了极高的吞吐量和资源利用率。无论是离线批量推理还是在线高并发服务,vLLM 都能以低延迟、高性价比运行大模型,是当前生产环境中不可或缺的推理利器。
下一步建议:尝试用 vLLM 部署你自己的开源模型,体验从单行 pip install 到千级并发服务的流畅过程,并根据实际负载调整参数,探索性能极限。