vLLM 论文学习笔记
论文链接: https://arxiv.org/abs/2309.06180
Introduction
背景
自回归过程很贵,让程序memory-bound,所以引入batch。
为了batch更大,内存管理很关键。大约30%的内存被KV cache占据。
现在的LLM服务框架管理内存不够高效,原因:将kv cahce放入连续的内存中。
KV cache的特点:
请求进来的时候,系统不知道KV cache会存在多长时间,最终会多大。
这一特点造成的问题:
- 传统系统会预留可能的最大空间,这个空间最后很可能用不上;即使最后用上了,在推理过程中的很长一段时间,这个空间处于闲置的状态;而且从外部看,GPU显存也会有external fragmentation的问题。
- 传统系统不能共享KV cache的前缀,因为它要保证KV Cache连续。在并行采样算法中,前缀是一样的,可以重复利用KV cache。
PagedAttetion核心思想:像操作系统一样,将block当成page,token当成byte,request当成process;所有block大小一致,减轻external fragmentation。
Preemptive request scheduling 与pagedAttention协同设计。
Background
Iteration-level scheduling:每生成一轮token就重新调度,batch是动态变化的。
LLM service的两个阶段:
- prompt phase:生成第一个token和kqv
- The autoregressive generation phase:用之前所有生成的token生成下一个token,复用之前的KV。
Batching技术的现有问题:
- 需要等待请求到来和上一个请求结束
- 请求的推理长度不一样
解决方案:fine-grained batching mechanisms。好处:
- 请求只需等待一轮token生成
- 调度机制+支持不等长序列的special GPU kernels消除padding影响。
LLM Serving的内存管理难点:
- KV Cache很大
- Beam search的共享KV Cache是变化的
- 当空间不足时删除或swap out KV Cache。
Method

Scheduler:调度分布式GPU
KV Cache manager:根据调度器的指令管理KV Cache。
PagedAttention
先对KV分块,块大小为B,则有公式:

KV Cache Manager
将内存划分成逻辑连续,物理上成多个分散的块。
block engine会分配一段连续的GPU DRAM,并划分成若干个物理的KV Block,CPU RAM同样,用于swapping。
维护一个block tables,记录逻辑和物理block的映射,并记录block内已经使用的大小。
一个decoding 迭代的步骤:
- 选择一些序列组成batch
- 为新请求的逻辑块分配物理块
- 拼接token
- 跑forward
- 读取旧KV
- 写入新KV
Parallel sampling
可以共享相同前缀的KV Cache
最后一个块出现分歧时,使用copy-on-write新开一个块。
Beam search中,不仅可以共享prompt,还有同台变化的更多共享模式。
Shared prefix
对于系统提示词可以预先储存共享KV缓存
Mixed decoding methods
vllm可以同时处理不同的decode模式,因为vllm使用统一的映射层,隐藏逻辑与物理块的复杂关系。
调度
使用first come first serve策略
如果所需KV Cache内存超出了显存:
以序列为单位进行两种调度:swapping和recomputation。具体用哪种取决于带宽和算力。
swapping:将显存的kv缓存放到cpu内存中,一旦发生了preempt,不接受新的请求,保证内存占用不大于显存占用。
recomputation:将kv cache直接释放,用到时再重新批量计算。
分布式执行
分布式模型计算:Attention的每个head是独立计算的;每个GPU负责一部分head的计算。Single Program Multiple Data模式,Megatron-LM风格tensor parallelism。
分布式KV Cache存储:每个GPU只需要保存自己负责的heads对应的KV
KV Cache管理和地址映射是中央scheduler统筹:每个GPU上的映射关系一样,只是储存的内容不一样。
整体架构:
Central Scheduler: 负责request 调度; KV Cache Manager; Block Table
|
| broadcast 控制信息
↓
|——GPU0:heads 0~7; kv shard 0
|——GPU1:heads 8~15; kv shard 1
|——GPU2:heads 16~23; kv shard 2
(GPU计算过程中使用all-reduce同步)
完整执行过程
- scheduler首先构造control message:当前batch中每个请求的input token ids和block table。
- scheduler将message广播给所有GPU
- GPU workers开始执行
- Attention层中,各worker根据block table读取KV Cache
- 使用all-reduce同步中间计算结果
- 最后,各worker将这一轮的sample tokens返回给scheduler形成循环
Implementation
vllm整体架构
vllm是端到端的大模型推理服务系统,组成:
- FastAPI前端:扩展了OpenAI 风格的API风格的接口,可以每个请求单独设置采样参数。
- GPU推理引擎:Python负责Scheduler、Block Manager、其他逻辑控制;CUDA C++负责PagedAttention算子;GPU通信使用NCCL;复用pytorch和Transformers能力。
用户请求
↓
FastAPI / OpenAI-style API
↓
Scheduler
↓
Block Manager / Paged KV Cache
↓
PyTorch Model Executor
↓
Custom CUDA PagedAttention
↓
NCCL multi-GPU communication
Kernel 优化
Fused reshape and block write:将新KV cache分成块,reshape成交适合读取的形状,写入内存。
Fusing block read and attention:直接根据block table从分页KV Cache中取K/V,然后马上计算attention,而不是先把K/V整理成连续内存。一个warp专门处理一个block,实现合并访存。
Fused block copy:不连续block的copy被batch成一次kernel launch
性能评估与消融实验
相比当时先进的Orca类方案,其吞吐量通常提升约2–4 倍
vLLM的注意力内核延迟比高FasterTransformer高20%–26%,但更高的批处理能力和显存利用率可以抵消
块太小,难以充分并行,管理开销更高;块太大,内部碎片增加,共享机会减少;大小默认为16token
块较小,带宽利用率低,重计算划算;块较大交换划算;块在16-64之间,表现相当。
讨论
分页适合:内存需求动态;性能受显存影响;提升利用率可以增加并发的场景。
| 最大并发 | 请求吞吐 | 输出吞吐 | 平均 TTFT | 平均 TPOT | 平均总延迟 |
|---|---|---|---|---|---|
| 1 | 3.73 req/s | 238.70 tok/s | 15.36 ms | 4.01 ms | 267.94 ms |
| 8 | 24.68 req/s | 1579.51 tok/s | 23.62 ms | 4.73 ms | 321.62 ms |