Lecture 05 · 缓存旧 K/V,新的需求仍须重新读取

R55 · 缓存旧 K/V,新的需求仍须重新读取

两次前向中出现了相同旧前缀。沿每层依赖找出真正不变的中间量,才能决定哪些计算可以缓存。

状态 b0

每层分别保存I gave的旧K/V。沿两层看它们各自来自哪次计算,辨认缓存的对象而非整句答案。

I gave → I gave her:每层各存 K / V因果读取:旧位置看不到新增 her层 1K / V · IK / V · gave层 2K / V · IK / V · gave新增词不会改变旧位置的因果依赖。

状态 b1

新her只生成当前Q/K/V,并追加本层K/V;新Q仍读旧项和自身项。省掉旧位置重算,没有省掉读取历史。

I gave → I gave her:每层各存 K / V因果读取:旧位置看不到新增 her层 1K / V · IK / V · gave新 Q / K / V · her层 2K / V · IK / V · gave新 Q / K / V · her旧 K/V 复用;新 Q 读取旧 K/V 与自己的 K/V。

状态 b2

修改前面的词后,依赖它的后续缓存必须重算。比较完整重算与缓存路径的logits,先确认是否仍为同一计算。

这里改变了旧前缀;只在末尾追加新token且保持其他条件时,前一状态的合法缓存仍可复用。

I gave → I gave her:每层各存 K / V因果读取:旧位置看不到新增 her层 1K / V · IK / V · gave新 Q / K / V · her层 2K / V · IK / V · gave新 Q / K / V · her旧前缀/位置/模型/mask 改变 → 相应缓存失效只追加新词,哪些旧计算仍然相同?

公式与算例详情

每层为什么能保留旧 K/V

确定的因果模型中,旧位置不能读取追加的未来 token:底层旧输入未变,逐层归纳后旧表示仍不变。因此每层可保存自己的旧 K/V;新 token 在这一层计算自己的 Q/K/V,以新 Q 读取旧位置及本位置的 K/V。缓存保存的是逐层张量,不是整句答案,也不是所有层共用一份 K/V。

等价性要求模型参数、前缀内容、位置编号、mask 和推理状态一致(例如关闭训练态 dropout)。修改旧前缀、错置 RoPE 位置或误用另一请求的缓存,都可能使旧值失效。双向结构追加位置会改变旧 query 的可读集合,因而高层旧表示可能改变;第一层若只投影未变的 token/位置 embedding,其旧 K/V 仍可能不变,但这个局部例外不能推出整套跨层缓存可复用。

已有数值检查能证明到哪里

历史本地两层 NumPy 因果模型在多个前缀及非零位置偏移下,cached 与完整重算 logits 的最大绝对差为 $2.22\times10^{-15}$。这是已保存的小模型等价性检查,不是本轮新实验、能力成绩或速度证明;该朴素实现的缓存路径当次实际更慢。后续 Notebook 的云端记录是另一项记录,应按各自配置阅读。

少算之后仍要付出的资源

KV payload 约为 $2LBTn_{kv}d_hs$ 字节:L 是层数,B 是 batch,T 是已存长度,$n_{kv}$ 是 KV 头数,$d_h$ 是每头维度,s 是每元素字节数,2 对应 K 与 V。缓存减少重复的前缀投影和层计算,但每个新 query 仍需读取越来越长的历史;是否更快必须实测,不能由等价性误差推导。

参考与采用

  • Caching — Hugging Face Transformers documentation:Causal fixed-prefix inference reuses each layer’s previous keys/values; new query reads old plus new K/V. 复核位置:Official documentation read: per-layer cache, old-token immutability, append/concatenate K/V, attention-mask dimensions and position handling.

原课页采用记录:M34 KV cache。页码均按PDF物理页计。

继续学习

要复核缓存等价性,先看CLS 03“5 · 为什么旧 K/V 能保留”,再在LAB 03“G · 旧 K/V 哪些可以沿用,哪些必须作废?”比较各步 logits 与计时;本页条件、双向例外与历史误差解释各记录的边界。要检验修改前缀后的失效,另读用这段字符流只验证 cache 的计算并看 LAB 03“路径C · 材料放得下,不代表采用了当前事实”的 stale cache 负对照。资源疑问则读prefill 与 decode 各做什么;G、路径 C 与资源估算分别回答不同问题。