【vLLM】vLLM 推理框架详解:从 PagedAttention 到生产级部署实战

关键词:vLLM、PagedAttention、连续批处理、KV Cache、大模型推理、显存优化

一、为什么需要 vLLM

大模型推理和训练不同,训练追求的是吞吐,而推理服务追求的是"低延迟 + 高并发 + 低成本"三者兼顾。在实际生产环境中,使用 HuggingFace Transformers 原生的 generate() 方法部署推理服务,往往会遇到两个致命问题:

  1. 显存浪费严重:自回归生成过程中,每个请求都需要缓存历史 token 的 Key/Value(也就是 KV Cache),传统做法是按"最大可能长度"预先分配一整块连续显存。但实际生成长度往往远小于预留长度,导致大量显存被闲置,实际利用率常常只有 20%~40%。
  2. 并发能力差:因为显存碎片化和过度预留,同一张卡能同时处理的请求数(batch size)被严重限制,直接拖累整体吞吐量。

针对这两个痛点,UC Berkeley 团队在 2023 年提出了 vLLM,其核心创新是 PagedAttention 算法。如今 vLLM 已经成为开源大模型推理服务的事实标准,广泛支持 Llama、Qwen、DeepSeek 等主流模型系列,单卡吞吐量相比朴素实现通常能提升 10~24 倍。

二、核心原理:PagedAttention

2.1 传统 KV Cache 管理的问题

在自回归生成中,每生成一个新 token,模型都需要用到之前所有 token 的 Key 和 Value 矩阵,这部分数据被称为 KV Cache。它有两个特点:

  • 体积巨大:以 13B 级别模型为例,单条较长序列的 KV Cache 就可能占用 GB 级别显存;
  • 动态增长:长度取决于输入和已生成的 token 数,事先无法精确得知。

传统推理引擎的做法是:按照"prompt 长度 + 最大输出长度"提前分配一整块连续显存。这种方式会产生两类浪费:

  • 内部碎片(internal fragmentation):预留空间没有被实际使用;
  • 外部碎片(external fragmentation):空间太小太散,无法分配给其他请求。

这背后的根本原因是:深度学习框架处理张量要求数据在显存中是连续存放的,而 KV Cache 的连续性要求恰恰是这一切低效的源头。

2.2 PagedAttention 的解决思路

PagedAttention 的灵感来自操作系统的虚拟内存分页机制:与其死板地为每个进程预留一整块连续物理内存,不如把物理内存切成固定大小的"页",再用一张页表把进程看到的连续逻辑地址映射到分散的物理页上。

vLLM 把这套思路平移到了 KV Cache 管理上:

  • 把显存预先划分成许多大小固定的 Block(块),每个 Block 默认可以存放 16 个 token 的 K/V 数据;
  • 每个请求的 KV Cache 在逻辑上仍然是"连续"的一串 Block,但物理上可以离散地分布在显存的任意位置;
  • 通过一张 Block Table(块表) 记录逻辑块到物理块的映射关系,在做 Attention 计算时按图索骥找到对应的物理块。

这样带来的直接收益是:因为每个 Block 只存固定数量的 token,对于任意一个请求,最多只会浪费"不到一个 Block"的空间(也就是最多浪费 block_size - 1 个 token 的容量),内部碎片被压缩到极小;同时因为分配是按需进行、随用随取,外部碎片也基本消失。

可以做一个类比:

操作系统虚拟内存 vLLM PagedAttention
进程 一个推理请求(sequence)
字节 Token
页(Page) Block
页表 Block Table

2.3 显存共享:Copy-on-Write

因为 KV Cache 是按块管理的,vLLM 天然可以在块粒度上做显存共享。典型场景包括:

  • Parallel Sampling / Beam Search :同一个 prompt 生成多条候选序列时,前缀部分的 KV Cache 完全相同,多个序列可以共享同一批物理 Block,只有在某个分支真正开始"分叉"(生成不同 token)时,才会触发 Copy-on-Write,为该分支单独复制一份 Block。
  • 前缀缓存(Prefix Caching):多个请求如果共享相同的系统提示词(System Prompt)或长文档前缀,也可以复用已经计算好的 KV Cache Block,省去重复计算。

这种共享机制进一步提升了显存利用率,尤其在多轮对话、共享模板等场景下效果显著。

2.4 显存不够时怎么办:抢占与恢复

由于 vLLM 采用"按需动态分配"策略,理论上存在显存被打满、但仍有请求未完成的情况。此时调度器会对部分请求执行抢占(Preemption) ,vLLM 采用的是 all-or-nothing 策略:被抢占的请求会释放其占用的全部 Block。恢复时有两种方式:

  • 重新计算(Recomputation):把被抢占请求当作一个新的 prompt,重新做一次 prefill;
  • 交换(Swapping):把 KV Cache 换出到 CPU 内存,待显存空闲后再换回来继续生成。

三、连续批处理(Continuous Batching)

如果说 PagedAttention 解决的是"显存怎么省",那连续批处理解决的就是"GPU 怎么不空转"。

3.1 传统静态批处理的问题

早期推理系统多采用静态批处理 :把一批请求打包送入模型,必须等这批请求全部生成完毕才能处理下一批。问题在于:

  • 不同请求的输出长度差异很大,短请求生成完了也要陪跑到最长的那条结束,GPU 利用率被拉低;
  • 新来的请求必须排队等待整批处理完,排队延迟高。

3.2 vLLM 的迭代级调度

vLLM 把批处理的粒度从"整个请求"下沉到"每一次前向计算(每个 decoding step)":

  • 每一步(step)结束后,调度器都会检查:哪些请求已经生成完毕(可以被移出批次),哪些新请求可以被纳入批次;
  • 新请求可以在任意一步"插队"加入正在运行的批次,无需等待整批结束;
  • 已完成的请求立刻释放资源(包括 KV Cache Block),显存和算力马上被下一位请求复用。

这种迭代级调度 + 动态批次的组合,就是 continuous batching。它和 PagedAttention 是互补关系:PagedAttention 让显存分配变得灵活可控,continuous batching 则让调度器可以放心地随时增删请求而不担心显存管理的复杂度。二者共同作用,使得 vLLM 在高并发场景下相比朴素实现能取得数量级的吞吐提升。

3.3 Prefill 与 Decode 两个阶段

一次请求的生命周期通常分为两个阶段:

  • Prefill(预填充) :对输入 prompt 做一次前向计算,一次性生成所有输入 token 的 KV Cache,这个阶段是计算密集型的(可以并行处理很多 token);
  • Decode(解码) :每次只生成一个新 token,并把新 token 的 K/V 追加进缓存,这个阶段是访存密集型的(每步只算一个 token,但要频繁读取显存中的历史 KV Cache)。

vLLM 的调度器需要在一个批次里同时安排处于 prefill 阶段和 decode 阶段的请求,这也是它工程实现里比较精细的部分。较新版本还引入了 Chunked Prefill(分块预填充),把长 prompt 的 prefill 计算切成若干小块,穿插在 decode 请求之间执行,避免一个长 prompt 的 prefill 独占整个 step,从而降低其他请求的排队延迟。

四、vLLM 的整体架构

一个典型的 vLLM 服务由三个核心模块协同工作:

  1. Scheduler(调度器):决定每一个 step 里,哪些请求参与本次前向计算,负责 KV Cache Block 的分配、抢占与回收;
  2. Block Manager(块管理器):维护物理 Block 的分配状态和每个请求的 Block Table,是 PagedAttention 在工程上的具体落地;
  3. Worker / Model Executor:真正执行模型前向计算的进程,负责加载模型权重、执行自定义的 PagedAttention CUDA/HIP Kernel,在多卡场景下还要处理张量并行的通信。

对外,vLLM 提供两种典型使用方式:

  • 离线批量推理 :直接调用 Python API(LLM 类 + generate),适合批量跑数据集、评测等场景;
  • 在线服务 :启动一个兼容 OpenAI API 协议的 HTTP 服务(vllm serve),可以直接作为聊天/补全接口对外提供服务,方便无缝替换 OpenAI 客户端。

五、快速上手示例

5.1 安装

复制代码
pip install vllm

5.2 离线批量推理

复制代码
from vllm import LLM, SamplingParams

prompts = [
    "介绍一下大语言模型推理加速的常见方法",
    "什么是KV Cache?",
]

sampling_params = SamplingParams(temperature=0.7, top_p=0.9, max_tokens=256)

llm = LLM(model="Qwen/Qwen2.5-7B-Instruct", tensor_parallel_size=1)
outputs = llm.generate(prompts, sampling_params)

for output in outputs:
    print(output.outputs[0].text)

5.3 启动 OpenAI 兼容的在线服务

复制代码
vllm serve Qwen/Qwen2.5-7B-Instruct \
    --tensor-parallel-size 1 \
    --gpu-memory-utilization 0.9 \
    --max-model-len 8192 \
    --port 8000

启动之后即可用标准 OpenAI SDK 或 curl 调用:

复制代码
curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen2.5-7B-Instruct",
    "messages": [{"role": "user", "content": "你好"}]
  }'

六、关键部署参数详解

参数 作用 调优建议
--gpu-memory-utilization 允许 vLLM 使用的显存比例(预留给 KV Cache Block 池) 单模型部署建议设到 0.85~0.95,多进程共卡需调低
--max-model-len 单条序列支持的最大上下文长度 按业务实际需求设置,越大单条请求占用的 Block 越多
--block-size 每个 KV Cache Block 存放的 token 数,默认 16 一般无需调整,特殊硬件/长上下文场景可尝试更大值
--tensor-parallel-size 张量并行的 GPU 数量 单卡放不下模型权重时使用,通常与单机 GPU 数对齐
--max-num-seqs 单个批次最多容纳的请求数 并发量大但显存有限时适当调低
--enable-prefix-caching 是否开启前缀缓存 多轮对话、共享 System Prompt 场景强烈建议开启
--quantization 权重量化方式(如 AWQ、GPTQ、FP8) 消费级显卡部署大模型的关键手段,可显著降低显存占用

七、分布式与多卡场景

当单张 GPU 显存无法容纳模型权重时,vLLM 支持:

  • 张量并行(Tensor Parallelism) :把每一层的权重矩阵切分到多张 GPU 上,各卡并行计算后做通信同步,通过 --tensor-parallel-size 指定;
  • 流水线并行(Pipeline Parallelism):把模型按层切分到不同 GPU/节点,适合超大模型的多机部署;
  • 结合 Ray 或 Kubernetes,可以进一步实现多实例的负载均衡与弹性扩缩容,满足生产级多租户场景的需求。

八、量化与显存优化

配合 AWQ、GPTQ、FP8 等量化技术,vLLM 可以把权重显存占用压缩到原来的 1/2 甚至 1/4,这意味着:

  • 消费级显卡也能跑起实用的 7B/13B 模型;
  • 同等显存下可以容纳更多 KV Cache Block,间接提升并发能力。

需要注意的是,量化通常会带来轻微的精度损失,生产环境上线前建议做充分的效果评估。

九、vLLM 的优势总结

  1. 显存利用率高:PagedAttention 将显存利用率从传统方案的 30% 左右提升到 85% 以上,内部/外部碎片基本消除;
  2. 吞吐量大幅提升:连续批处理配合 PagedAttention,同等硬件下并发能力可提升数倍到数十倍;
  3. 长上下文友好:分页式 KV Cache 管理天然适配长文档、长对话等超长上下文场景;
  4. 生态成熟:无缝兼容 HuggingFace 模型库和 OpenAI API 协议,社区活跃,主流大模型(Llama、Qwen、DeepSeek 等)基本第一时间获得支持;
  5. 部署门槛低:单条命令即可拉起服务,结合量化技术后中小团队也能低成本私有化部署。

十、小结

vLLM 之所以能成为当下开源 LLM 推理服务的事实标准,核心在于它用一套"操作系统式"的思路重构了 KV Cache 的内存管理方式:PagedAttention 解决了"显存怎么分配更省"的问题,连续批处理解决了"GPU 怎么调度更满"的问题,两者相辅相成,共同把大模型推理服务的吞吐天花板提高了一个量级。对于需要自建大模型推理服务的团队而言,无论是单卡部署中小模型,还是多卡张量并行部署超大模型,vLLM 目前都是工程成熟度和社区活跃度最高的选择之一。


参考资料

  • vLLM 官方文档:https://docs.vllm.ai
  • Efficient Memory Management for Large Language Model Serving with PagedAttention(SOSP 2023)
  • vLLM GitHub 仓库
相关推荐
卷无止境16 分钟前
Kilo CLI 到底是什么
人工智能·后端·python
2601_9557596226 分钟前
ClaudeAPI企业运营数据周报怎么做
大数据·人工智能
Anita-lee26 分钟前
北美智能电动牙刷市场退货率控制与海外售后服务体系构建指南
大数据·人工智能
XR12345678831 分钟前
办公大楼组网选型决策树:TCO 与三大品牌优劣对比总结
算法·决策树·机器学习
QYRdata34 分钟前
24.7%年复合增长率!工业元宇宙平台2026-2032年发展预期明确
大数据·网络·人工智能
武汉誉天34 分钟前
AI运维课程都学什么内容?
运维·人工智能
做萤石二次开发的哈哈37 分钟前
萤石蓝海AIoT一站式工作台新增海康消防烟感接入:多端智慧消防应用一站生成
人工智能·物联网·萤石开放平台·蓝海aiot一站式工作台·aiot开发·海康消防烟感·报警推送
cd_9492172138 分钟前
AI生成的纹理需要在Substance Painter里继续修改吗?PBR材质精修与角色纹理流程
人工智能·材质·substance painter
阳明山水1 小时前
Mamba路径如何建模长程时序依赖
人工智能·深度学习·算法·机器学习·架构