首页优化地图方法索引基础概念
返回技术汇总表 ↗

M017 · 独立详解

KV 分层、卸载与淘汰:缓存放哪里,什么时候搬回来

区分正在使用的历史 KV 与等待复用的前缀,算清容量、搬运和重算的取舍。

内存与数据搬运调度与并行详解已编写
视频讲解待制作

这篇文章的小视频尚未制作;可以先阅读下方文字详解。

本页目录

01 · 缓存省了计算,为什么又成为负担

自回归模型把每层历史 token 的 K/V 存下来,后续 Decode 直接读取。上下文越长、同时活跃请求越多,设备 KV 占用越大。缓存复用还可能留下已完成请求的前缀,等待未来相同输入;这些数据不再是当前请求必需的,却仍占设备容量。

把设备内存想成工作台、主机内存想成旁边仓库。分层是为不同数据选择存放位置;卸载是把数据移出设备;回迁是使用前搬回来;淘汰是删除某个缓存副本。后三者的正确性和成本不同。

依据:Transformers · How Caching Works ↗ · TensorRT-LLM · KV Cache System ↗

02 · 两类 KV,不能用同一条“冷数据”规则

对象何时再次需要合适的理解
活跃请求的完整历史 KV标准全上下文 Attention 每个 Decode 步都可能读取较早 token 不等于冷数据。卸载后仍须按层回迁,或用兼容执行方式读取。
空闲的可复用前缀未来兼容请求命中时可以留在设备、移到主机,或淘汰后重新 Prefill。
模型规定窗口之外的 KV该模型后续层不再读取时释放依据模型原有可见性;不能将窗口规则任意加到全 Attention 模型上。

同一物理块可能被多个请求引用。一个请求结束,不代表这个块已空闲。缓存键还要匹配模型版本、token、位置、适配器与隔离条件;“数值看起来相同”不是可靠的身份判据。

依据:vLLM · 前缀缓存哈希、块引用与生命周期设计 ↗ · Transformers · KV cache策略与逐层卸载 ↗

03 · 一次安全卸载,要经过哪些状态

教学示意 · 不代表硬件实测
设备副本有效
→ 提交 D2H(设备到主机),保留源和目标
→ 等复制完成,确认主机副本有效
→ 设备使用者全部结束后,才可释放设备块
→ 使用前提交 H2D(主机到设备)
→ 等回迁完成,更新块表后才执行 Attention

任务提交返回时,复制可能还没完成。如果此时覆盖源块,主机保存的就可能是另一请求的数据。回迁也需要可用设备块;设备容量耗尽时,应先排队、抢占或回收可安全释放的块,而不是先发任务再期待空间出现。

淘汰空闲前缀后,下次命中不了就从 token 重算;暂停活跃请求也可选择丢 KV 后从保留的完整历史重建,但会增加计算和恢复延迟。永久删除模型仍应读取的上下文,又不回迁、不重算,则改变 Attention 结果。

依据:PyTorch 2.14 · CUDA stream、等待与内存生命周期 ↗ · TensorRT-LLM · KV Cache System ↗

04 · 一个 512 MiB KV 的容量账本

自设普通 GQA 示例:32 层、8 个 KV 头、每头 128 元素、每元素 2B、4096 个已处理 token。每 token KV = 2×32×8×128×2 = 131,072B = 128 KiB;完整缓存为 512 MiB,每层 16 MiB。这里不含批次、并行切分、元数据、对齐和增长余量。

执行方式教学账本仍须计入的峰值
全部常驻设备保存 32 层,共 512 MiB新 token、工作区、其他请求。
逐层卸载主机存历史;当前层与预取层各 16 MiB两层合计 32 MiB 只是理想工作集;尚未完成的写回、双缓冲与分配池可能继续占设备空间。
只卸载空闲前缀从设备挪走一个 512 MiB 前缀副本已有活跃引用的共享块不能直接回收,主机也要有预算。

05 · 省容量为什么可能变慢

假设一个方向的有效带宽为 25 GiB/s,只搬 512 MiB 的理想时间下界是 0.5/25 秒 = 20 ms。如果每个 Decode 步都从主机读回这些历史,单向复制已是 20 ms;若某执行方案还写回完整历史,双向串行字节成本是 40 ms。只写新增 KV、保留若干热层等策略会改变这笔账。

对空闲前缀则不同:回迁通常发生在复用时,而不是每个生成步都搬整个前缀。512 MiB 回迁和重新计算该前缀哪个便宜,要比较实际 H2D、Prefill 耗时、排队、容量占用及后续收益;不能只按前缀长度猜。

搬回缓存,还是重新Prefill?

一次空闲前缀复用;假设设备落点充足、缓存兼容、无排队和其他开销。H2D是理想字节下界,实际迁移决策还要看主机预算和竞争。

预取下一层可以把回迁与当前层计算重叠。实际等待还取决于可提前多久、复制资源是否被其他请求占用,以及 Attention 本身是否争用设备带宽。带宽下界和理想重叠都不等于实测 TPOT。

06 · 两种现成入口,各自解决什么

Transformers 接入片段 · 本机未运行设备模型,需匹配模型及版本支持
from transformers import AutoModelForCausalLM, AutoTokenizer
# model/tokenizer 初始化、设备放置及依赖由使用者配置
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
output = model.generate(**inputs, max_new_tokens=64,
                        cache_implementation="offloaded")

Transformers 的 offloaded cache 按层组织活跃历史 KV,异步预取后续层。TensorRT-LLM 的 host_cache_size 则提供被设备淘汰块的主机复用层。这两个入口都用主机内存,但不能把“活跃逐层缓存卸载”和“空闲复用块的二级缓存”当作同一个服务策略。

下方 CPU 脚本将一个小模型的缓存复制到模拟主机仓库,再恢复继续前向,与常驻缓存比较;还验证复制完成前禁止复用源块。它验证缓存内容和状态依赖,没有 GPU/NPU 搬运性能含义。

依据:Transformers · KV cache策略与逐层卸载 ↗ · TensorRT-LLM · KV Cache System ↗

07 · 容量紧张时,怎样决定留、搬、删

  • 先标出引用者与恢复途径:正在使用、复制中、已完整保存、可由 token 重建。
  • 对空闲前缀估计命中概率、可省 Prefill、占用字节及回迁成本;设置设备和主机各自预算。
  • 对活跃请求考虑暂停恢复的代价、优先级与延迟目标,避免反复换入换出。
  • 选择缓存块、层或请求作为迁移单位,兼顾连续传输、块表一致性与复制批量。

LRU 是一种按最近使用时间淘汰的策略,不知道前缀重算代价;优先级和保留期可以表达额外价值。过度缓存会挤占正在生成的 KV,容量看似省了计算,却可能增加抢占和尾延迟。

依据:TensorRT-LLM · KV Cache System ↗ · vLLM · 前缀缓存哈希、块引用与生命周期设计 ↗

08 · 怎样确认它是收益,而不只是放得下

检查项需要报告什么
容量设备峰值、主机峰值、固定页/锁页内存、各层临时副本与可用并发。
服务相同请求轨迹下 TTFT、TPOT 分位数、吞吐、抢占次数和命中率。
搬运每步/每命中的实际字节、H2D/D2H、关键路径等待及共享链路争用。
正确性常驻 vs 卸载;跨块边界、共享前缀、取消、重复迁移、恢复模型版本。

如果常驻方案放得下,卸载可能只降低速度;如果常驻无法承载目标并发,卸载的价值可能在服务容量。分别写清与哪一个可行基线比较。

09 · NVIDIA 与昇腾怎样对照

两侧都需要主机容量、复制通路、执行依赖和兼容 KV 内核。上述 CUDA 引擎入口不能直接证明某昇腾版本支持同一功能;昇腾先核对服务引擎功能矩阵,再检查 CANN 异步复制与 Host 内存条件。跨设备或远端 KV 传输还涉及通信协议与缓存身份,不等同于本地 CPU 卸载。

依据:vLLM Ascend · 支持功能矩阵(main) ↗ · CANN Community 9.1.0 · aclrtMemcpyAsync与Host内存约束 ↗

10 · 自查与扩展实验

  • 为什么全上下文 Attention 的最早 token 仍可能是热数据?
  • 512 MiB 前缀一次回迁 20 ms、重新 Prefill 12 ms时,还可能为什么保留主机副本?考虑设备容量与排队。
  • 给卸载状态图增加取消操作:复制仍在进行时,哪两块内存不能立刻交给新请求?

流程位置与关联方法

这个方法可能出现在多个位置;计算线包含模型计算与算子实现,执行线包含运行时、内存和通信。

资料与核查范围

原理依据以原始论文和官方文档为主;算例与时间线是教学推导。文档核查日期:2026-10-10。引用 main / latest 文档时,实际接口以安装版本为准。

代码为接入片段或教学伪代码;本页没有声称完成 NVIDIA / 昇腾硬件实测。

← 返回总表中的 M017继续阅读:图编译、形状专门化与自动调优 →
AI Infra 知识库 · 总览 → 独立讲解网站更新 2026-10-08
搜索知识库

搜索方法与基础概念 · Esc 关闭