机器学习平台技术栈之 vLLM:重新定义大模型推理的高性能引擎
机器学习平台技术栈之 vLLM:重新定义大模型推理的高性能引擎
随着 ChatGPT 的横空出世,生成式 AI 进入了“百模大战”的时代。各大企业和研究院不仅关注如何训练出更聪明的基座模型(如 Llama 3, Qwen, ChatGLM),更将目光聚焦在了大规模部署与推理成本上。
在大语言模型(LLM)的生命周期中,训练是一次性的密集投资,而推理(Inference)则是持续不断的开销。传统的深度学习推理框架(如原生 PyTorch 或 HuggingFace Transformers)在处理 LLM 的自回归生成任务时,面临着极低的 GPU 利用率和极其昂贵的显存开销。
为了推倒这堵“推理显存墙”,来自加州大学伯克利分校(UC Berkeley)的研究团队推出了 vLLM。它不仅霸榜了各大开源推理吞吐量榜单,更成为了当下机器学习平台(ML Platform)技术栈中不可或缺的基石组件。
本文将剥茧抽丝,深度剖析 vLLM 的核心概念、架构设计、以及它是如何通过 PagedAttention 技术彻底重塑大语言模型推理引擎的。
1. 痛点解析:为什么 LLM 推理如此艰难?
要理解 vLLM 的伟大之处,首先要明白在它诞生之前,LLM 推理遇到的是什么物理与系统层面的瓶颈。
1.1 LLM 推理的两阶段:Prefill 与 Decode
LLM 的文本生成是一个自回归(Auto-regressive)过程,每一次前向传播只能生成一个 Token。一个完整的请求生命周期分为两个阶段:
- Prefill(预填充阶段):将用户输入的 Prompt 一次性输入给模型,计算所有输入 Token 的注意力(Attention),并生成第一个输出 Token。这一阶段计算密集(Compute-bound),能充分利用 GPU 的矩阵乘法单元(Tensor Cores)。
- Decode(解码阶段):用之前生成的 Token 加上原始 Prompt,生成下一个 Token,直到遇到停止符
<EOS>。这一阶段每一次迭代计算量很小,但内存访问密集(Memory-bound)。
1.2 KV Cache 显存刺客
在 Decode 阶段,为了避免每次生成新 Token 时都重新计算之前所有 Token 的 Key 和 Value 向量,推理引擎会把它们缓存在 GPU 显存中,这就是 KV Cache。
随着并发请求数(Batch Size)和上下文长度(Context Length)的增加,KV Cache 的体积会呈线性甚至超线性膨胀。显存容量成为了限制吞吐量(Throughput)的绝对木桶短板。
1.3 传统框架的显存碎片危机
在此前的系统(如 ORCA 或 FasterTransformer 早期版本)中,系统会为每个请求预先分配(Pre-allocate)一段连续的显存用于存储 KV Cache。
假设模型最大支持 2048 个 Token,系统就会直接划走 2048 个 Token 的显存空间。但现实中,绝大多数用户的请求加上回答只有几百个 Token。
这就导致了极其严重的显存碎片问题:
- 内部碎片(Internal Fragmentation):预分配了 2048 长度,实际用了 500,剩下的 1548 长度被死霸占,造成极大浪费。
- 外部碎片(External Fragmentation):不同的请求长度不一,内存中存在众多无法拼接的小块连续空间,导致无法接纳新请求。
据论文统计,原生系统的 KV Cache 显存浪费率高达 **60%-80%**!这就导致你的 A100/H100 虽然算力空闲,却因为没有显存容纳新请求而只能干瞪眼。
2. 核心概念:PagedAttention 与操作系统的神迹
遇到内存碎片问题,计算机科学的老祖宗们在设计操作系统时其实早就给出了终极解法——虚拟内存与分页(Virtual Memory Paging)。
vLLM 的划时代意义,就是将 OS 的显存分页机制完美移植到了 LLM 的注意力机制计算中,提出了 PagedAttention。
2.1 什么是 PagedAttention?
PagedAttention 摒弃了为每个请求分配连续显存的做法,而是将每个序列的 KV Cache 划分为固定大小的 Block(数据块)。
- 每个 Block 专门存放固定数量(例如 16 个)Token 的 Key 和 Value 向量。
- 这些物理 Block 在 GPU 显存中不需要是连续的。
- 通过一个Block Table(块表),将请求序列的“逻辑块”映射到显存中的“物理块”。
1 | graph TD |
2.2 概念之间的关系与收益
- 消除外部碎片:所有的物理块大小相同(如 16 Tokens),内存池管理器(BlockManager)只需要像分配页一样 pop 出空闲块即可,从根本上消灭了外部碎片。
- 根除内部碎片:按需分配(On-demand Allocation)。推理生成了第 17 个 Token 时,才去申请第 2 个 Block。整个系统只会浪费最后一个未填满的 Block 的非常少量的碎片(< 4%)。
- **内存共享 (Copy-on-Write)**:这是对于 Beam Search(束搜索)或并行采样的神级优化。多个返回序列可以共享同一个 Prompt 的物理块,只有在其分叉(Diverge)生成不同 Token 的那一刻,系统才复制并分配新的块。
3. vLLM 的高并发调度架构设计
解决了底层的显存存储问题,如何让海量的请求持续、连贯地榨干 GPU 的算力?vLLM 在控制面实现了一个极其精妙的异步调度引擎。
3.1 总体架构全景 (Architecture Overview)
vLLM 也是控制面与数据面分离的经典架构。
1 | graph TD |
- API Server: 通常是一个 FastAPI 应用,兼容 OpenAI 的接口标准,接收高并发的流式(Streaming)请求。
- AsyncLLMEngine: 系统的中央枢纽,维护整个系统的状态,接收新请求并管理未完成的请求(Request Tracker)。
- Scheduler (调度器): 决定在下一个前向传播(Forward Pass)周期,应该取哪些请求组成 Batch 给到 GPU 运算。它依赖于 BlockManager 来判断当前 GPU 显存是否足够。
- Block Space Manager: “显存的大管家”,跟踪物理 Cache 块的分配与释放。
- Workers & CacheEngine: 实际执行计算的兵卒。它可以是一个单卡进程,也可以依托 Ray + Megatron/NCCL 进行张量并行(Tensor Parallelism)的多卡计算。CacheEngine 负责在 GPU 之间、或者 CPU-GPU 之间管理和搬运 KV Cache。
3.2 Continuous Batching (动态连续批处理)
在早期的推理框架中,Batching 是请求级别(Request-level)的。当几个请求组成一个 Batch 后,必须等最长的那个请求处理完毕,整个 Batch 才能退出并读入下一批请求。这导致 GPU 在大量时间内都在等待(因为部分短序列已经生成完毕处于闲置状态)。
vLLM 实现了 Continuous Batching (连续批处理,也叫 Iteration-level scheduling)。
引擎调度的粒度缩小到了每一次 Token 生成的迭代(Iteration)。
每次生成一个 Token 后,调度器会:
- 踢出(Finish)已经生成
<EOS>的请求,回收它的 Blocks。 - 只要显存 BlockManager 报告还有空闲的物理块,立刻把处于 Pending 队列的新请求塞入当前的 Batch 中参与下一个 Token 的运算。
这种细胞级别的细粒度流水线操作,使得 vLLM 的 Batch Size 永远保持在水位线的极限,极大拉升了系统的吞吐量。
3.3 抢占 (Preemption) 与 Swap 置换调度
尽管有 PagedAttention 加持,随着生成过程不断申请新 Block,显存依然可能在某次迭代被耗尽(Out of Memory)。
此时 vLLM 调度器绝不会崩溃,而是触发**抢占机制 (Preemption)**。
当剩余空闲物理块不足以支撑下一轮解码时,调度器会暂停某些优先级较低的序列(Suspend),并选择以下两种策略之一:
- Swap(交换到 CPU): 将低优先级序列的 KV Cache 物理块,通过 PCIe 总线 Swap-out 断排到 Host CPU 内存中。等 GPU 有空余时,再 Swap-in 回来继续生成。
- Recompute(重新计算): 直接丢弃 KV Cache 块。等需要恢复该序列时,重走一遍此时显存不再拥挤的 Prefill 预填充阶段。虽然废算力,但省去了从内存搬运的数据带宽开销(如果模型很长,重新计算反而可能比 PCIe 带宽搬运更快)。
4. 走向深水区:关键技术细节剖析
作为企业级机器学习平台的基础设施,vLLM 除了基础的 PagedAttention,还堆砌了大量工业级的 Hardcore 优化。
4.1 自动张量并行 (Auto Tensor Parallelism)
为了处理诸如 Llama 3 70B 乃至千亿参数的模型,单张 GPU 放不下模型权重。vLLM 内置了与 Megatron-LM 兼容的张量并行(TP)与流水线并行(PP)机制。
- Ray 整合: 用户在启动时指定
tensor_parallel_size=4,vLLM 会在后台自动拉起一个 Ray Cluster(或使用多进程 multiprocessing),并在 4 张卡上分别加载模型的一定分片(例如列切割、行切割)。 - 分布式 KV Cache: 在 TP 模式下,Attention 的多个 Head 会被切分到不同 GPU。vLLM 的 BlockManager 同样也是分布式的,卡 0 的 CacheEngine 只管理卡 0 负责的那些 Heads 的物理块。
- 每一步 Transformer 计算结束,系统通过高度优化的 Custom All-Reduce CUDA Kernel 聚合结果,不仅省去了 NCCL 初始化的某些额外开销,还通过图优化(Graph Capture/CUDA Graphs)把通信损耗做到了极致。
4.2 Chunked Prefill (分块预填充)
由于系统是 Continuous Batching 的,如果有在 Decode 阶段的老请求正在飞速一个一个吐字,此时突然涌进来一个包含 4000 个 Token 超长 Prompt 的新请求。
如果是传统引擎,必须先把这个 4000 Token 的请求一口气算完(Prefill 阶段耗时极长),这就会导致那几个正在打字的老请求发生严重的卡顿(Stall),首字延迟(TTFT)与字间延迟(TPOT)同时雪崩。
vLLM 引入了 Chunked Prefill 技术:
如果设定的 max_num_batched_tokens 为 512,vLLM 会把那个 4000 长度的 Prompt 切碎,在第一个 Iteration 只计算它的前 512 个 Token(更新这部分状态),并与老请求的 1 个 Decode token 混合在一起处理。
虽然拉长了长文本的首字延迟(合理),但这保证了正在流式输出的旧请求享有丝滑般恒定的打字响应体验。这在面向 C 端的 Chatbot 场景(如 ChatGPT)中是生死攸关的用户体验保证。
4.3 Automatic Prefix Caching (APC前缀缓存)
在多轮对话(Multi-turn Chat)、长文本 RAG(如基于企业百页研报问答)的场景下,Prompt 往往包含了极其雷同的大面积 System Prompt 或长文本背景。
vLLM 利用了 PagedAttention 基于区块的数据结构天然优势,引入了基于 Radix Tree(基数树)的 Prefix Caching。
1 | graph TD |
当一个新的请求进来时,系统会将它切成一系列的逻辑块(Logical Blocks),然后去树上做前缀匹配。
如果另一个用户的上一个请求已经计算过 "You are an expert... Here is a document: ..." 并且其物理块依旧被缓存在 GPU 里面。
vLLM 会直接将新请求的前 N 个逻辑块映射到已经存在好的物理块上(并增加引用计数 RefCount)。不仅这部分内存被零成本复用,这部分长文本的 Attention 预计算耗时更直接归零(缓存命中相当于 TTFT 的指数级提升)。
5. vLLM 在企业 AI 平台生态中的位置
在实际的大型企业 ML 平台(如基于 Kubernetes + Kubeflow 的基础设施)中,vLLM 从不是一个孤立的 Python 脚本进程。它早已作为最强势的推理基座被标准化:
- 容器化与网关层接入:将 vLLM 打包到 Docker 镜像中,并通过 Kubernetes 的 Deployment 暴露。前面配合本文前一个章节提到的 Aibrix 或是 Envoy/Nginx 网关,进行大模型流量的汇聚与状态路由分发。
- KServe / Seldon 集成:vLLM 原生支持被 KServe OCI 标准或者 Triton Inference Server 的 Backend 纳管,享受 K8s 水平自动伸缩扩展(HPA)的红利。
- 监控与可观测性:vLLM 直接通过
/metrics端口向 Prometheus 暴露大量基于大模型原生的关键指标:vllm:num_requests_running/vllm:num_requests_waitingvllm:gpu_cache_usage_perc(极其重要的 KV Cache 碎片占用率指标,决定是否需要自动扩容)- 细粒度的 TTFT (首字延迟) 和 TPOT (输出字延迟) P99 指标。
6. 总结:重新定义推理
从 vLLM 的架构演进可以看出,系统工程(Systems Engineering)正在疯狂重塑 AI 领域。
大模型本身是一个充斥着算力暴力的数学奇迹,而 vLLM 则是系统科学家面对这头算力巨兽开出的一剂良方。它敏锐地察觉到内存不仅需要大、更是需要被“精密管理”。
通过 PagedAttention(虚拟内存映射),它消灭了碎片、拯救了显存;通过 Continuous Batching(细粒度调度),它无缝填补了流水线空隙、榨干了每一滴 GPU Tensor Core 矩阵运算算力。结合 Prefix Caching, Chunked Prefill, 以及高度工程化的 CUDA Kernel,vLLM 让原本只存在于顶尖科技巨头实验室的大模型高吞吐并发推理,变成了所有创业公司和 AI 平台都能轻易触及的基础设施红利。
掌握 vLLM 的内在原理,就是掌握在这个大模型暴涨时代,如何用最省钱、最高效的姿势驾驭最聪明的大脑的终极密码。





