Skip to content

KV缓存与PagedAttention — 概念

传统 KV Cache 的问题

在标准 Transformer 推理中,每个请求的 KV 缓存需要预分配最大长度的连续显存:

问题:

  • 显存浪费:预分配最大长度,实际使用远小于此
  • 碎片化:不同请求释放后产生不连续的空闲区域
  • 无法共享:相同前缀的请求各自保存独立副本

PagedAttention 原理

PagedAttention 借鉴操作系统虚拟内存的分页机制:

核心概念

概念说明
Block(块)固定大小的 KV 缓存单元,默认 16 tokens
Block Table(块表)虚拟块到物理块的映射表
Block Pool(块池)所有可用物理块的集合
Reference Counting(引用计数)跟踪每个物理块的引用数,支持共享

块的生命周期

前缀缓存(Prefix Caching)

Prefix Caching 允许具有相同前缀的请求共享 KV 缓存块:

实现方式:

  1. 每个 block 计算内容的哈希值
  2. 新请求的 block 哈希与已有 block 匹配
  3. 匹配成功则复用已有物理块(引用计数 +1)
  4. 不匹配则从空闲池分配新块

哈希计算

block_hash = hash(block_content, parent_block_hash)

这是链式哈希:每个块的哈希依赖其内容和父块的哈希,确保相同序列位置上的相同内容产生相同哈希。

KV 缓存卸载(KV Cache Offloading)

当 GPU 显存不足时,vLLM 支持将 KV 缓存卸载到其他存储层级:

分层策略

层级延迟容量适用场景
GPU HBM~ns有限活跃请求的 KV 缓存
CPU RAM~us较大被抢占的请求
SSD/Disk~ms很大长期不活跃的请求

文件系统分层(FileSystem Tiering)

新增的纯 Python 磁盘后端二级缓存层:

关键特性:

  • DualQueueThreadPool:分离读写队列,读操作优先处理
  • 原子写入:先写临时文件,再 rename 确保一致性
  • O_DIRECT I/O:绕过页缓存,减少内存拷贝
  • 哈希子目录:将 KV 块按哈希映射到子目录,避免单目录文件过多

MooncakeStore 多组支持

MooncakeStore 连接器现在支持混合注意力模型的多组 KV 缓存:

  • MooncakeStoreCoordinator:计算每个 KV 缓存组的 load/store mask
  • 多 TokenDatabase:每组 KV cache 维护独立的 ChunkedTokenDatabase
  • LCM 块对齐:跨异构 KV 缓存组的块对齐(使用最小公倍数)
  • 指标子系统MooncakeStoreConnectorStats 跟踪每次操作的延迟、字节数、p90 延迟和错误率

Block 大小选择

block_size 的选择影响性能:

block_size优点缺点
小(8)更精细的显存管理,浪费更少更多的元数据开销
中(16)平衡选择(默认)
大(32)更少的元数据开销更多显存浪费

相关概念