01 · KV 为什么会越来越大
每个新位置会在每一层产生 K 和 V。后续 Decode 读取历史 KV,以免重新执行全部旧 token 的投影与前向。请求长度事先未知,多请求又随时完成或取消;如果按最大长度保留连续空间,容易发生过量预留和外部碎片。
教学容量公式:每 token 的 KV 字节数 = 2×层数 L×KV 头数 Hkv×head dimension d×每元素字节 b。GQA 的 KV 头数和查询头数不同;MLA、量化、并行切分和实际缓存布局需要另算。
依据:Transformers · How Caching Works ↗ · PagedAttention 原始论文 ↗
02 · 地址映射如何工作
将一个请求的 token 位置划成固定大小的逻辑块。系统为每个逻辑块分配任意空闲物理块,在 block table 里记录映射。Attention 内核通过表项找到实际 K/V,而不是假设整个请求的缓存都连续。
logical_block = token_position // block_size
offset = token_position % block_size
physical_block = block_table[request][logical_block]
K = k_cache[physical_block, offset, ...]
V = v_cache[physical_block, offset, ...]进入新块时再向空闲池申请,结束时归还。分页仍有最后一块的内部空闲和元数据开销,不是完全没有浪费。共享不可变前缀块时需要引用计数;写入可能需要 Copy-on-Write。是否做前缀查找、是否允许共享,是额外策略,不是分页自动完成。
依据:vLLM · Paged Attention 内核设计 ↗ · TensorRT-LLM · KV Cache System ↗
03 · 三个请求的分配例子
自设示例:每请求最大预留 64 token,当前 A/B/C 长度分别为 17、33、8。连续最大预留方案占 192 个 token 槽位;块大小为 16 时需要 2+3+1=6 个块,即 96 个槽位。有效 token 共 58 个;分页空闲 38 个,最大预留空闲 134 个。
| 请求 | 逻辑块 → 物理块(示意) | 块内有效位置 |
|---|---|---|
| A / 17 token | 0 → 7,1 → 2 | 16 + 1 |
| B / 33 token | 0 → 4,1 → 9,2 → 1 | 16 + 16 + 1 |
| C / 8 token | 0 → 5 | 8 |
物理块顺序可以打乱,但 token 的逻辑位置与因果关系保持原样。A 从 17 增长到 18,不用新分配;从 32 到 33 才需要第三个块。C 结束后物理块 5 可供新请求使用。
调整块大小,观察内部空闲
请求长度 17 / 33 / 8;不计块表、共享与预分配空闲池。04 · 系统和算子必须一起配套
- 系统维护空闲块池、请求长度、block table 与引用计数。
- Prefill / Decode 写 KV 时使用相同映射,读 Attention 时传入正确块表和位置。
- 取消与异步执行时,确认设备已经不再访问旧块,才允许复用。
- 启用前缀缓存时,核对 token、模型版本、适配器、位置处理与缓存隔离条件。
不要直接把设备块表当作操作系统的真正虚拟内存页表。它是引擎和内核共同约定的数据结构;页大小、布局与后端相关。源码阅读可以先从 vLLM 的 paged attention 内核设计和运行时块分配分别入手。
依据:vLLM · Paged Attention 内核设计 ↗ · TensorRT-LLM · KV Cache System ↗
05 · 为什么主要提升服务容量和吞吐
减少浪费后,可用同样内存承载更多并发请求,连续批处理就有机会组成更有效的批次。但块表查询和分散访问也有成本,所以“可承载请求更多”不等于“一个请求的单次 Attention 一定更快”。
| 评估项目 | 如何比较 |
|---|---|
| 缓存容量 | 固定模型、dtype、上下文分布和 KV 预算,记录有效 token 与实际分配。 |
| 服务性能 | 固定到达率和延迟目标,比较可承载吞吐、OOM / 抢占、TTFT 与 TPOT。 |
| 正确性 | 跨越块边界、不同长度、取消、共享前缀及分支生成的输出与基线比较。 |
06 · NVIDIA 与昇腾怎样对照
NVIDIA 引擎中可看到 vLLM / TensorRT-LLM 的分块 KV 管理及对应 Attention 后端。迁移到昇腾时要匹配引擎的块表协议、CANN 内核缓存格式和设备能力。相同分页理念可以采用不同布局;不能直接复用 CUDA kernel,也不能只替换分配器而忽略读取内核。
依据:vLLM · Paged Attention 内核设计 ↗ · TensorRT-LLM · KV Cache System ↗
07 · 自查与小实验
- 保持三个长度不变,将块大小改为 8、16、32,比较内部空闲;为什么更小的块也有代价?
- 模拟释放 B 的全部块,再给新请求分配,检查没有仍被 A 引用的块被误回收。
- 把 Prefix Cache 与分页 KV 分别开关,避免把两者收益混成一个指标。
流程位置与关联方法
这个方法可能出现在多个位置;计算线包含模型计算与算子实现,执行线包含运行时、内存和通信。
资料与核查范围
原理依据以原始论文和官方文档为主;算例与时间线是教学推导。文档核查日期:2026-10-10。引用 main / latest 文档时,实际接口以安装版本为准。
- PagedAttention 原始论文 ↗
- Transformers · How Caching Works ↗
- vLLM · Paged Attention 内核设计 ↗
- TensorRT-LLM · KV Cache System ↗
代码为接入片段或教学伪代码;本页没有声称完成 NVIDIA / 昇腾硬件实测。