4、vLLM核心特性:PagedAttention、Continuous Batching、量化支持、分布式推理

4.1 核心原理:PagedAttention——让KV Cache不再“碎片化”

大语言模型推理时,每个请求都会产生一组键值缓存(KV Cache),用于存储已生成 token 的注意力中间结果。传统推理框架为每个请求预分配连续显存,但请求的实际生成长度无法预知,导致大量显存被浪费或不足。vLLM 引入操作系统虚拟内存的分页思想,将 KV Cache 划分为固定大小的块(Block),按需分配,彻底解决显存碎片化问题。

传统方式:连续预分配 已用 60% 预留但空闲 → 显存浪费,长序列易OOM PagedAttention:分页块管理 块0 块1 空闲 块3 空闲 逻辑块序列 L0 L1 L2 L3 物理块(显存) P0 P1 P2 P3 空闲 空闲 块表(Block Table) L0→P0 | L1→P2 | L2→P1 | L3→P3 优势对比 ✗ 传统:浪费 40% 显存,无法共享 ✓ PagedAttention:利用率 95%+,支持共享

PagedAttention 的核心是块表(Block Table),它记录每个逻辑块对应的物理块地址。生成新 token 时,只需在块表中追加一条映射;多个序列还可以共享相同的物理块(如并行采样时),进一步节省显存。实测中,PagedAttention 可将 KV Cache 显存利用率从 40% 提升至 95% 以上。

4.2 方法流程:Continuous Batching——动态调度请求

传统推理采用静态批处理:一批请求必须全部完成后才处理下一批。若某个请求生成长文本,其他短请求只能空等。vLLM 的 Continuous Batching(连续批处理)在token 级别动态调度:每步迭代时,只要某个请求完成,立即插入新请求,保持 GPU 始终满载。

调度流程(每步迭代):

  1. 从等待队列中取出请求,加入当前迭代批次;
  2. 检查每个请求的 KV Cache 块是否足够,不足则分配新块;
  3. 执行一次前向传播,为批次中所有请求各生成 1 个 token;
  4. 若请求达到 max_tokens 或输出 <EOS>,将其移出批次;
  5. 重复步骤 1-4,直到所有请求完成。
# vLLM 调度参数示例(vLLM 0.6+)
from vllm import LLM, SamplingParams

llm = LLM(
    model="meta-llama/Llama-3-8B-Instruct",
    max_num_batched_tokens=8192,   # 每批次最大 token 数
    max_num_seqs=256,              # 最大并发序列数
    enable_prefix_caching=True,    # 前缀缓存加速
)

sampling_params = SamplingParams(
    max_tokens=512,
    temperature=0.7,
    top_p=0.9,
)
outputs = llm.generate(["请解释量子纠缠", "写一首关于秋天的诗"], sampling_params)

Continuous Batching 的收益在混合负载下尤为明显。例如,同时处理 100 个短问答和 10 个长文生成请求时,传统批处理会让短请求等待长请求完成,而连续批处理能让短请求在 2-3 秒内返回,整体吞吐量提升 2-3 倍。

4.3 量化支持:降低显存门槛

vLLM 原生支持多种量化方案,允许用更低的精度存储模型权重,从而在相同显存下运行更大模型或提高并发度。常用量化格式包括:

量化格式位宽适用场景显存节省精度损失
FP16/BF1616位默认基线0%无
INT8 (W8A8)8位通用场景~50%极小
INT4 (GPTQ/AWQ)4位大模型部署~75%可接受
FP8 (E4M3)8位浮点Hopper/Ada GPU~50%极小
# 使用 AWQ 量化模型
llm = LLM(
    model="TheBloke/Llama-2-7B-Chat-AWQ",
    quantization="awq",
    dtype="float16",
    gpu_memory_utilization=0.9,
)

# 或使用 GPTQ
llm = LLM(
    model="TheBloke/Llama-2-13B-Chat-GPTQ",
    quantization="gptq",
    revision="gptq-4bit-32g-actorder_True",
)

实践建议:若 GPU 显存 ≤ 16GB,推荐使用 4-bit 量化(AWQ/GPTQ)运行 7B-13B 模型;若显存 ≥ 24GB,可优先尝试 FP16 或 FP8,以获得最佳生成质量。量化后务必用验证集测试输出质量,避免关键任务精度下降。

4.4 分布式推理:多卡并行策略

当单卡显存无法容纳模型时,vLLM 通过分布式推理将模型切分到多张 GPU。它支持两种并行模式:张量并行(Tensor Parallelism)和流水线并行(Pipeline Parallelism)。

  • 张量并行(TP):将每个 Transformer 层的权重矩阵按行/列切分到多卡,所有卡同步计算同一层。适合单节点内多卡(NVLink 互联),通信开销低。
  • 流水线并行(PP):将模型按层切分为多个阶段,每张卡负责若干层,数据按顺序流经各卡。适合跨节点场景,但存在流水线气泡。
# 单节点 4 卡张量并行
llm = LLM(
    model="meta-llama/Llama-3-70B-Instruct",
    tensor_parallel_size=4,   # 使用 4 张 GPU
    dtype="bfloat16",
)

# 跨节点(2 节点 × 4 卡)
# 启动时设置:--tensor-parallel-size 4 --pipeline-parallel-size 2
llm = LLM(
    model="meta-llama/Llama-3-70B-Instruct",
    tensor_parallel_size=4,
    pipeline_parallel_size=2,
    distributed_executor_backend="ray",
)

vLLM 还支持 数据并行(DP),即每张卡持有完整模型副本,处理不同请求,适合吞吐量优先的场景。实际部署中,常将 DP 与 TP 结合:例如 8 卡 GPU,可配置 tensor_parallel_size=4 和 data_parallel_size=2,实现“模型并行 + 请求并行”的双重加速。

4.5 案例与场景:组合使用核心特性

以一个典型的在线聊天机器人服务为例,展示四个特性的协同工作:

部署配置:

  • 模型:Llama-3-8B-Instruct(AWQ 4-bit 量化)
  • 硬件:2 × A10G(24GB)
  • vLLM 参数:tensor_parallel_size=2,max_num_seqs=128
  • 负载:平均 50 并发用户,混合短问答和长文生成

运行效果:PagedAttention 使 KV Cache 显存占用降低 60%,连续批处理保证 GPU 利用率稳定在 90% 以上,量化让模型权重仅占 6GB 显存,剩余显存全部用于 KV Cache 和中间激活。最终单实例吞吐量达到 1200 tokens/s,P95 延迟低于 800ms。

4.6 误区与复盘:常见配置陷阱

误区 1:量化一定导致质量严重下降

实际上,4-bit 量化对 7B 以上模型的生成质量影响通常小于 5% 的指标下降。但若任务涉及数学推理或代码生成,建议使用 AWQ 而非 GPTQ,并开启 --quantization 的 act_order 优化。

误区 2:TP 越大越好

张量并行需要频繁的 AllReduce 通信。当 TP 超过 4 且模型小于 13B 时,通信开销可能抵消计算加速。经验法则:单卡能放下模型时优先 DP;放不下时 TP 不超过节点内 GPU 数。

误区 3:忽略前缀缓存

多轮对话中,历史消息反复计算造成浪费。vLLM 的 enable_prefix_caching 可缓存公共前缀的 KV 块,实测多轮场景下可减少 30%-50% 的重复计算。务必开启此选项。

复盘一个真实案例:某团队在 4×A100 上部署 70B 模型,最初配置 tensor_parallel_size=4 且未开启前缀缓存,吞吐量仅 300 tokens/s。优化后:改用 tensor_parallel_size=2 + pipeline_parallel_size=2,开启前缀缓存,并将 KV 块大小从 16 调整为 32,吞吐量提升至 850 tokens/s,显存占用反而下降 20%。这说明特性组合的调优比单一参数调整更重要。