PagedAttention 与块管理
核心思想
借鉴 OS 虚拟内存的分页机制:逻辑连续的 KV 序列 → 物理不连续的固定大小 block
每个 block 存
block_size个 token 的 K/V页表(block_table)维护逻辑块号 → 物理块号映射
为什么需要分页?
内存碎片
连续分配,不同长度请求导致大量外部碎片
固定块大小,只有末尾块有内部碎片
最大序列长度
预分配最大长度,浪费严重
按需分配,用多少分多少
前缀共享
每个请求独立拷贝
Copy-on-Write,引用同一物理块
碎片分析
内部碎片:最后一个块可能未填满 →
waste = block_size - (seq_len % block_size)碎片率:
internal_frag = avg_waste / block_sizeblock_size 越大 → 内部碎片越大,但页表越小
vLLM 默认 block_size = 16
Prefix Caching
相同 system prompt 或 few-shot 前缀 → 对应的 KV 块可以跨请求复用
索引方式:hash(prefix_tokens) → block_table
vLLM 的 Automatic Prefix Caching:用 radix tree 做前缀匹配
命中时跳过 prefill → TTFT 大幅降低
Copy-on-Write
fork 时新序列共享源序列的物理块(ref_count +1)
只有写入(decode 追加)时才真正复制 → 节省分配开销
适合 beam search、并行采样等场景
关键参数
block_size
每块 token 数
16
num_gpu_blocks
GPU 上的块数
按显存自动计算
num_cpu_blocks
CPU offload 块数
0 或按需
面试一句话
"PagedAttention 通过虚拟内存分页消除了 KV 缓存的外部碎片,使显存利用率接近 100%,同时支持前缀缓存和 CoW 共享。"
最后更新于