vLLM:基于 PagedAttention 的高吞吐推理引擎

FreeGuideOnline 最新 2026-06-14

什么是 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 到千级并发服务的流畅过程,并根据实际负载调整参数,探索性能极限。