4. vLLM核心概念

vLLM 之所以能在众多推理框架中脱颖而出,核心在于它对传统 LLM 推理引擎的三大痛点——显存碎片化、请求排队低效、KV Cache 管理粗放——进行了系统性的架构重构。理解 PagedAttention、Continuous Batching 与 KV Cache 这三者的协同关系,是掌握 vLLM 性能调优的前提;而吞吐量与延迟指标则是衡量这些优化是否有效的最终标尺。本章将深入拆解这些核心概念,并给出可操作的监控与调优方法。

vLLM 核心机制协同关系图 并发请求流 Req1, Req2, ... ReqN Continuous Batching 迭代级调度 动态拼批 / 抢占 KV Cache 管理器 物理块分配 引用计数 / 写时复制 PagedAttention 逻辑块 → 物理块映射 块表 (Block Table) GPU 显存块池 Block 1, Block 2, ... 块大小: 16 tokens 性能衡量指标 • 吞吐量: tokens/s (输出) / req/s • 延迟: TTFT (首), TPOT (每) • 显存利用率: 有效KV / 总分配 调度决策 分配/释放 物理块 三者协同:Continuous Batching 决定“谁执行”,PagedAttention 决定“KV存哪里”,指标决定“效果如何”

4.1 PagedAttention:从虚拟内存到显存管理的跨越

核心原理

PagedAttention 是 vLLM 的基石,其灵感来源于操作系统中的虚拟内存分页机制。在传统推理框架中,KV Cache 需要一块连续的内存空间,且大小需在请求开始时按最大序列长度预留。这导致两个严重问题:一是内部碎片(预留空间未用满),二是外部碎片(不同请求的缓存空间无法共享)。PagedAttention 将 KV Cache 划分为固定大小的物理块(通常每个块可存储 16 或 32 个 的 KV 向量),每个请求的逻辑 KV Cache 通过一个“块表”映射到非连续的物理块上。这种设计使得显存利用率接近 100%,且仅在需要时分配新块。

判断方法与操作流程

在实际部署中,判断 PagedAttention 是否生效,最直接的方法是观察 vLLM 启动日志中的 GPU KV cache size 参数。若该值大于 0,说明已启用。调优时需关注两个关键参数:

  • --block-size:默认 16。较小的块减少内部碎片,但增加块表开销;较大的块反之。对于长序列生成(如代码生成),建议 32。
  • --max-num-seqs:限制并发序列数,防止块池被单个请求耗尽。
# 启动时指定块大小和并发数
python -m vllm.entrypoints..api_server \
  --model meta-llama/Llama-3.1-8B-Instruct \
  --block-size 32 \
  --max-num-seqs 256

案例拆解:显存碎片化导致的 OOM

某团队使用 HuggingFace Transformers 部署 70B 模型时,即使 batch size 设为 1,在长对话场景下仍频繁 OOM。分析发现,Transformers 为每个请求预分配了最大长度(2048 tokens)的连续 KV Cache,而实际平均只用到 800 tokens,显存浪费率超过 60%。迁移到 vLLM 后,PagedAttention 按需分配物理块,同样显存下并发能力提升了 4.2 倍,且未再出现 OOM。复盘经验:对于对话式 AI 或长文档处理场景,PagedAttention 的收益远大于短文本分类任务。

风险提示:PagedAttention 的块表本身也占用显存。当 block-size 过小且序列极长时,块表可能成为新的瓶颈。建议监控 block_manager 的 CPU 内存占用。

4.2 Continuous Batching:迭代级调度的威力

核心原理

传统的 Static Batching 必须等待一个 batch 中所有序列生成完毕,才能释放显存并接收新请求。这导致 GPU 在 batch 尾部出现大量空闲(气泡)。Continuous Batching(连续批处理)将调度粒度从“序列级”细化为“迭代级”(即每个 decode 步骤)。vLLM 的调度器在每个 forward pass 前检查所有序列的状态:若某序列已生成结束标记(EOS)或达到最大长度,立即将其移出 batch,并插入排队中的新请求。这种机制让 GPU 始终处于高饱和计算状态。

操作流程与参数配置

  1. 启用开关:vLLM 默认启用 Continuous Batching,无需额外参数。
  2. 控制抢占策略:当显存不足时,调度器会抢占(preempt)部分序列。vLLM 支持两种模式:recompute(重新计算被抢占序列的 KV)和 swap(将 KV 换出到 CPU)。
  3. 调整调度窗口:通过 --max-num-seqs 限制单次迭代的最大序列数,避免过度抢占。

实战场景:混合负载下的吞吐量优化

某 SaaS 平台同时处理短问答(平均 50 tokens)和长文总结(平均 1500 tokens)。使用 Static Batching 时,长文请求会阻塞短请求达数秒。切换 vLLM 后,Continuous Batching 让短请求在长文请求的 decode 间隙被插入执行。实测结果:P95 延迟从 4.2s 降至 1.1s,整体吞吐量提升 3.8 倍。关键调优点是将 --max-num-seqs 设为 128,并启用 --enable-prefix-caching 以加速重复前缀(如系统提示词)。

经验提醒:若你的请求长度方差极大,建议开启 --use-v2-block-manager,其更精细的块管理能进一步减少抢占频率。

4.3 KV Cache 深度管理:显存利用率的隐形战场

核心原理与量化对比

KV Cache 的大小由模型维度(层数、头数、头维度)和序列长度决定。以 Llama-3.1-8B 为例,每个 的 KV 占用约 0.5MB(FP16)。若并发 100 个序列,平均长度 1024,则需约 50GB 显存——远超模型权重本身。vLLM 通过三种手段优化:前缀缓存(相同前缀共享 KV)、写时复制(多个采样序列共享初始 KV)、量化(FP16→INT8)。

优化手段原理适用场景显存节省
前缀缓存相同 prompt 前缀的 KV 复用多轮对话、RAG 固定指令30%-70%
写时复制beam search 等采样分支共享 KVbeam search 解码分支数倍数级
KV 量化将 KV 从 FP16 降为 INT8/FP8显存极度紧张约 50%

监控与调优方法

使用 nvidia-smi 观察显存占用时,需区分“模型权重”和“KV Cache”。vLLM 提供了更精确的指标:gpu_cache_usage_perc(通过 /metrics 端点暴露)。当该值持续高于 90% 时,说明 KV Cache 接近饱和,应降低并发或启用量化。

# 通过 Prometheus 查询 KV Cache 使用率
curl http://localhost:8000/metrics | grep vllm:gpu_cache_usage_perc

案例复盘:前缀缓存带来的成本下降

某客服机器人每天处理 200 万次请求,其中 80% 的请求共享相同的系统提示词(约 500 tokens)。启用 --enable-prefix-caching 后,KV Cache 命中率提升至 65%,单次请求的 TTFT 从 380ms 降至 120ms。同时,由于显存压力减小,可以将 GPU 实例从 4×A100 缩减至 2×A100,年度成本降低约 40%。复盘要点:前缀缓存的效果高度依赖业务负载的重复度,建议先分析 prompt 前缀的分布再决定是否启用。

4.4 吞吐量与延迟指标:性能的度量衡

核心指标定义

衡量推理性能不能只看单一数字,需区分吞吐量和延迟,并进一步拆解延迟的构成:

  • 吞吐量(Throughput):单位时间生成的 数(tokens/s)或处理的请求数(req/s)。关注 GPU 的饱和利用。
  • TTFT(Time To First ):从请求发出到收到第一个 的时间。影响用户感知的“响应速度”。
  • TPOT(Time Per Output ):生成每个输出 的平均时间。影响生成流畅度。
  • 端到端延迟:TTFT + TPOT × 输出长度。这是用户实际等待的总时长。

测量方法与工具

vLLM 内置了 --metrics 端点,可输出上述所有指标。推荐使用 vllm bench 工具进行压测:

# 压测命令示例
python benchmarks/benchmark_serving.py \
  --backend vllm \
  --model meta-llama/Llama-3.1-8B-Instruct \
  --dataset ShareGPT \
  --num-prompts 500 \
  --max-concurrency 50

压测时需关注 吞吐量-延迟曲线:随着并发数增加,吞吐量先上升后趋于平稳,而 TPOT 会逐渐恶化。最佳工作点通常在吞吐量达到峰值 80% 的位置。

案例拆解:定位性能瓶颈

某团队压测发现吞吐量仅为理论值的 40%。通过指标拆解:

  1. TTFT 正常(50ms),排除调度问题。
  2. TPOT 异常高(120ms),而 GPU 利用率仅 60%。
  3. 进一步观察发现 gpu_cache_usage_perc 仅为 30%,但 CPU 内存占用极高。
  4. 定位到问题:--max-num-seqs 设置过大(1024),导致 CPU 侧的数据预处理和 tokenizer 成为瓶颈。
  5. 将参数调至 256 后,TPOT 降至 45ms,吞吐量提升 2.1 倍。
总结复盘:性能调优应遵循“先看指标,再定瓶颈,后调参数”的流程。切勿盲目堆 GPU 数量。vLLM 的三大核心机制(PagedAttention、Continuous Batching、KV Cache 管理)是相互关联的整体——调度器决定 KV 的分配时机,PagedAttention 决定分配效率,而指标则反馈整个系统的健康度。建议在生产环境建立指标监控看板,重点关注 gpu_cache_usage_perc、avg_tpot 和 p99_tpot 三个指标。