vLLM 深读:用 PagedAttention 撑起高并发 LLM 推理
拆解 vLLM 的推理引擎架构:PagedAttention 如何管理 KV cache,分页机制如何减少显存碎片,以及它作为 OpenAI 兼容服务端的部署方式与同类框架的定位差
一个 70B 模型跑在 4 张 A100 上,并发数从 8 提到 32,显存先炸了——不是因为权重放不下,而是 KV cache 放不下。更准确地说,是 KV cache 被浪费掉了。vLLM 要解决的就是这个浪费问题,它的答案叫 PagedAttention。
先看浪费在哪里
自回归推理的每一步,模型都要为每个请求缓存此前所有 token 的 Key 和 Value 张量,这就是 KV cache。传统实现按「请求可能达到的最大长度」预分配一块连续显存,请求结束时整块释放。
问题出在三个地方:请求实际生成长度远小于预留上限;同一请求的 KV cache 在物理上必须连续,导致显存里到处是塞不进新请求的碎片;并行采样(一个 prompt 出多个候选)时,多个候选共享同一段前缀,却各存一份。
vLLM 的做法是把操作系统的虚拟内存分页搬到显存里。KV cache 被切成固定大小的 block,逻辑上连续、物理上可以不连续,用一张 block table 做映射。请求按需申请 block,用完归还,碎片从「按请求粒度」降到「按 block 粒度」。前缀相同的序列可以指向同一批物理 block,靠引用计数管理写时复制。
这套机制是 vLLM 的论文主题(SOSP 2023,标题即《Efficient Memory Management for Large Language Model Serving with PagedAttention》),也是它区别于其他推理框架的起点。
引擎的分层结构
README 没有给出目录树,但它的能力清单本身已经勾勒出清晰的分层。按请求从进入到吐出的路径,可以把 vLLM 拆成五层:
| 层次 | 核心职责 | README 中的对应能力 |
|---|---|---|
| 接入层 | 对外暴露服务协议 | OpenAI 兼容 API server、Anthropic Messages API、gRPC |
| 调度层 | 决定每步跑哪些请求、跑多少 token | Continuous batching、chunked prefill、prefix caching |
| 显存管理层 | 分配与回收 KV cache | PagedAttention、block table、多 LoRA 的独立显存管理 |
| 执行层 | 实际的前向计算与算子 | FlashAttention / FlashInfer / FlashMLA / Triton 等 attention kernel;CUTLASS / TRTLLM-GEN / CuTeDSL 的 GEMM 与 MoE kernel;piecewise 与 full CUDA/HIP graph |
| 模型层 | 把权重映射成可执行的计算图 | Hugging Face 模型无缝接入、200+ 模型架构、量化格式支持 |
请求流转大致是这样:接入层把 HTTP 或 gRPC 请求翻译成内部请求对象;调度层把它塞进 continuous batching 的批次里,按 token 预算切片(chunked prefill 让长 prompt 不必独占一个完整批次);显存管理层为它分配 KV block 并维护 block table;执行层用对应硬件的 attention kernel 完成计算,CUDA graph 把重复的 kernel 启动开销压掉;结果以流式方式回传。
几个关键点值得单独拎出来:
Continuous batching 是吞吐的来源。批次不是静态的,每个 decode step 结束后都有请求完成、也有新请求加入,调度器在 step 边界重组批次,GPU 不空转。
Prefix caching 与 PagedAttention 是同一套机制的延伸。系统提示词、few-shot 示例这类重复前缀,其 KV block 只算一次、被多个请求共享,直接省掉重复 prefill。
Disaggregated prefill / decode / encode 把预填充和解码拆到不同实例上跑。这两阶段的算力特征相反:prefill 是计算密集的大矩阵乘,decode 是显存带宽密集的逐 token 生成,混在一起会互相拖累。拆开后各自按最优配比扩缩容。
投机解码(n-gram、suffix、EAGLE、DFlash)在 decode 阶段用小模型或启发式方法先猜若干 token,再让大模型一次验证,把串行的逐 token 生成变成批量的并行校验。
量化覆盖 FP8、MXFP8/MXFP4、NVFP4、INT8、INT4、GPTQ/AWQ、GGUF、compressed-tensors、ModelOpt、TorchAO。这一层的意义在于:显存省下来,就能多放 KV block,并发上限随之抬高。
并行策略提供 tensor、pipeline、data、expert、context 五种并行。expert parallelism 是给 MoE 模型准备的,DeepSeek-V3、Mixtral、Qwen-MoE、GPT-OSS 这类架构的专家分布在不同设备上。
硬件后端不止 NVIDIA。AMD GPU、Intel GPU、x86/ARM/PowerPC CPU 是原生支持,Google TPU、Intel Gaudi、IBM Spyre、Huawei Ascend、Rebellions NPU、Apple Silicon、MetaX GPU 通过硬件插件接入。这也解释了 topics 里为什么同时出现 cuda、amd、tpu、blackwell。
跑起来只要两行
README 的安装段极短,推荐用 uv:
bashuv pip install vllm vllm download-kernels # precompiled kernels for faster startup
第二条命令值得注意——预编译 kernel 是为了缩短启动时间,说明 vLLM 的算子层有相当一部分需要针对硬件编译,不是纯 Python 包一装就能跑。开发场景可以按文档从源码构建 wheel。
安装完成后起一个 OpenAI 兼容服务,客户端就能用标准的 /v1/chat/completions 协议调用。README 明确列出了 OpenAI-compatible API server、Anthropic Messages API 和 gRPC 三种接入方式,意味着现有基于 OpenAI SDK 的应用基本不用改代码就能换后端。
结构化输出走 xgrammar 或 guidance,工具调用和推理内容解析有专门的 parser。多 LoRA 支持覆盖 dense 与 MoE 层,一个基座模型可以挂多个适配器对外服务。
它和谁不是一类东西
素材给的对照项目里,只有 SGLang 是真正的同赛道对手,其余几个只是共享「Transformer」这个 topic。
| 项目 | 定位 | 与 vLLM 的关系 |
|---|---|---|
| vLLM | LLM 推理与服务引擎,PagedAttention 管理 KV cache,主打高吞吐高并发 | 本体 |
| SGLang | LLM 与多模态模型的高性能 serving 框架,强项在结构化输出与 agent workflow | 直接竞品,同属 serving 层 |
| whisper.cpp | Whisper 语音识别的纯 C/C++ 移植,本地离线推理 | 不同模态、不同部署形态,不构成替代 |
| fish-speech | 开源 TTS,文本转语音 | 任务不同,属于被服务对象而非服务框架 |
| heretic | 去除模型审查限制的工具 | 模型后处理工具,与推理引擎无交集 |
| mmdetection | 目标检测工具箱与 benchmark | 视觉任务,PyTorch 训练/推理工具链 |
vLLM 与 SGLang 的差异不在「谁快」这种没有素材支撑的判断上,而在能力重心:vLLM 的叙事主线是显存管理与调度(PagedAttention、continuous batching、prefix caching、disaggregated serving),SGLang 的站内简介把结构化输出和 agent workflow 放在最前面。前者更像通用推理底座,后者更贴应用编排。两者都提供 OpenAI 兼容接口,选型时看的应该是模型覆盖、硬件后端和部署形态是否匹配,而不是抽象的性能口号。
谁该用它
需要把开源模型变成线上服务的团队。你的场景是:手里有一批 Hugging Face 上的模型(decoder-only、MoE、多模态、embedding、reward 都在支持范围内),要对外提供 API,并发量不是个位数,硬件可能是 NVIDIA 也可能是 AMD、TPU 或国产加速卡。vLLM 的 200+ 模型架构覆盖和插件式硬件后端就是为这种不确定性准备的。
反过来,如果只是本地跑一个模型做实验,或者要做的是语音识别、语音合成、目标检测,那 whisper.cpp、fish-speech、mmdetection 才是对的工具——它们和 vLLM 不在同一层,不构成选择困难。
数字与入口
仓库创建于 2023-02-09,最近一次推送在 2026-10-18。当前 94013 stars、23508 forks、8982 open issues,Apache-2.0 许可,Python 编写。近九千个未关闭 issue 是这类高速迭代基础设施项目的常态,也侧面说明它的使用面有多宽。
回到开头那个场景。vLLM 没有让显存变大,它只是让每一块显存都不再被浪费——分页、共享、按需分配,把「能放几个请求」从预留式估算变成实际利用率问题。高并发的门槛,往往就卡在这道浪费上。