完整前缀在 Layer 1…L 中逐层重跑
中间节点表示“在每一层内对完整前缀执行 QKV、attention 与 MLP”,不是先跑完所有层再统一生成 QKV。
观察点 01
每生成一个词,都把整段历史重新算一遍
若不保存历史 K/V,第 t 步要重新让完整前缀经过各个 Transformer 层,包括旧位置的投影、attention 与 MLP。随着序列增长,重复计算越来越多。
- 历史重复计算非常多
- 缓存占用几乎没有
KV Cache 用显存换重复计算,是自回归服务的核心状态。
每层都会保存历史 token 的 K/V,避免下一轮重新计算旧 token。缓存随层数、上下文、KV 头数、head dim、位宽和并发共同增长。
完整前缀在 Layer 1…L 中逐层重跑
中间节点表示“在每一层内对完整前缀执行 QKV、attention 与 MLP”,不是先跑完所有层再统一生成 QKV。
观察点 01
若不保存历史 K/V,第 t 步要重新让完整前缀经过各个 Transformer 层,包括旧位置的投影、attention 与 MLP。随着序列增长,重复计算越来越多。
KV Cache 用显存换重复计算,是自回归服务的核心状态。
状态传导图
attention 读取的是允许访问的 K/V[1:t],其中包含本层当前 k_t/v_t;每条序列的逻辑状态不能无条件混用。
观察点 02
Prefill 建好初始缓存;decode 在每层为新增位置计算 Q/K/V,把当前 K/V 与旧缓存逻辑合并成 K/V[1:t],当前 Q 再读取这段可见历史做 attention。更新缓存与读取可由同一个 kernel 融合。
Cache 省掉旧位置的整层重复前向,但历史读取量和逻辑容量仍随长度增长。
两条替代路线(A / B,不是先后步骤)
路线 A 通过更少 KV 头共享,路线 B 通过 latent + 解耦 RoPE key;实际质量、kernel 与读流量要按模型实现评估。
观察点 03
GQA 让多个 Q 头共享较少 K/V 头,MQA 更极端;DeepSeek-V2 MLA 缓存低维内容 latent 与较小的解耦 RoPE key,并可用矩阵吸收完成注意力,而非显式物化完整每头 K/V。
压 KV 改的是单 token 缓存宽度,不会让上下文长度项消失。
状态传导图
块表负责逻辑到物理映射;连续批处理是可与之配合、但并不等同的调度机制。
观察点 04
逻辑上连续的 KV 被映射到离散物理块,请求增长时分配新块,结束后释放引用;无人引用的块可被重新分配/淘汰,启用 prefix cache 时也可能暂留等待命中。共享前缀还能引用相同块。
PagedAttention 优化的是内存管理,不是改变注意力数学。
你现在应该能解释:PagedAttention 优化的是内存管理,不是改变注意力数学。
大模型生成不是一次性吐完,而是一个 token 一个 token往外写。KV Cache 让模型不用反复重算历史,是推理加速的命门;但它也会随着上下文和并发线性膨胀,成为长上下文服务最容易爆的显存账。
| 先分两段 | Prefill 是读题并生成笔记,Decode 是每写一个新 token 都翻笔记。 |
| PagedAttention | 借鉴操作系统分页:笔记本不要求连续摆放,用块表把逻辑顺序映射到显存块。 |
| 核心权衡 | 保留所需历史能避免重算;可见历史越长,KV 的容量与读取压力通常越大,可承载并发越少。 |
在标准因果全注意力中,第 t 个位置要看 1...t。如果每个 decode step 都把完整前缀重新过一遍 Transformer,就会重复计算旧位置。KV Cache 的作用很简单:把历史 token 在每层 attention 里的 Key / Value 存下来;下一步只让新增位置经过各层,产生自己的 Query / Key / Value,追加新 K/V 后查询历史缓存。
新位置的 q_t 仍要和允许访问的 K[1:t] 做注意力;旧 K/V 不再重算,新 k_t/v_t 会写入本层缓存。滑窗或稀疏注意力只读取其中的子集。
← 左右滑动查看完整链路 · 打开原图
Q(t) 读 K[1:t] 形成权重,再读 V[1:t] 得到输出,新 K(t)/V(t) 在逐层 QKV 路径追加。并行处理 prompt,并给每层建好历史 K/V。在排队、网络与预处理受控时,长 prompt 的 prefill 计算通常是 TTFT 的主要组成之一。
常规自回归每步为每条活跃序列新增一个 token,并读取权重和所需历史 KV;低 batch 等形状下常受带宽限制,具体仍看模型、硬件与 kernel。
缓存所需历史可避免重算;但上下文越长、并发越高,逻辑容量和读取量通常越大。
1+(1+2)+(1+2+3)+(1+2+3+4)=20;有 KV Cache 时,每轮只新增一个 query,配对数为 1+2+3+4=10。推广到长度 T:朴素重跑的 attention 累计是 Θ(T³),缓存后的 dense 增量 attention 累计仍是 Θ(T²),并非 O(1)。这条公式是理解长上下文推理的钥匙。它解释了为什么 GQA/MQA/MLA 会流行,也解释了为什么 128K/1M 上下文真正贵在服务端。
B=等长活跃序列数,L=层数,S=每条序列缓存 token 数,H_kv=KV 头数,D=每头维度,乘 2 是 K 和 V。这是标准 MHA/GQA 的逻辑、分片前容量:变长 batch 应改为对各序列 S_i 求和;张量/上下文/流水并行会改变单 rank 驻留量,prefix sharing 会改变物理去重,block 对齐、量化 scale、元数据和临时 buffer 又会增加实现开销。MLA 也不能直接套用。
| 场景 | 粗略 KV Cache | 为什么重要 |
|---|---|---|
| Mistral-7B-v0.3, 32K | 32×32768×8×128×2×2 bytes = 4GiB/sequence | 官方配置为 32 层、8 KV 头、hidden size 4096 / 32 query heads,因此 head_dim 128;按 BF16/FP16 2 bytes 粗算。这里尚未扣分片或 prefix sharing。 |
| Llama 3.1 70B, 128K | 80×131072×8×128×2×2 bytes = 40GiB/sequence | 发布配置为 80 层、64 query heads、8 KV 头、hidden size 8192,因此 head_dim 128;按 BF16/FP16 粗算,未计运行时开销。 |
| 同一 70B,1 Mi token | 1,048,576 = 8×131,072,逻辑 KV 约 320GiB/sequence | 只说明架构与 dtype 不变时的线性外推;模型是否支持该窗口、如何分片,以及 MLA、KV quant、滑窗等都要另算。 |
这里故意用“量级”而非固定数字,因为真实模型的 L/H_kv/D 差异很大。判断方法是看模型配置:层数、query head 数、KV head 数、head_dim 和 KV dtype。
MHA、MQA、GQA 的主要区别是一个 KV 头服务多少 Query 头;DeepSeek-V2 的 MLA 则把内容相关的 K/V 联合压到低维 latent,并把 RoPE(Rotary Position Embedding,旋转位置编码)分量解耦。它们都缩窄每 token 缓存,但机制并不相同。
| 方法 | 怎么省 | 代价 / 代表 |
|---|---|---|
| MHAMulti-Head Attention | 通常每个 Query 头对应自己的 K/V 头 | KV 头最多;不是“表达力一定更强”的保证,而是容量/带宽成本最高的基线。 |
| MQAMulti-Query Attention | 所有 Query 头共享 1 组 K/V | 在 MHA/MQA/GQA 且其余维度相同的比较中缓存最小;原论文报告降低增量解码的 KV 带宽,并观察到轻微质量退化,不能外推到所有训练配方。 |
| GQAGrouped-Query Attention | Query 头分组,每组共享一组 K/V | 介于 MHA 与 MQA;GQA 论文的 uptraining 实验达到接近 MHA 的质量和接近 MQA 的速度,不是对所有模型的无条件保证。 |
| MLAMulti-head Latent Attention | 缓存压缩的内容 latent 与较小的解耦 RoPE key;用矩阵吸收/等价变换消费 latent,无须显式物化完整每头 K/V | DeepSeek-V2 的特定设计;论文相对 DeepSeek 67B 报告 KV Cache 降低 93.3%,实现和 kernel 更复杂,不能把比例泛化到所有 MLA。 |
| KV Quant | 把 KV 从 FP16/BF16 降到 INT8/INT4/更低 | 直接降低元素位宽与潜在流量;scale/元数据、反量化 kernel、硬件支持和精度损失都要计入。 |
| Sliding / Sparse | 让某些层或位置只保留/读取历史子集 | 这些路径不再执行完整全局注意力;不同层可能仍保留全局窗口,容量、流量和远程召回要按具体模式算。 |
PagedAttention 论文针对当时要求 KV tensor 连续、并按潜在最大输出长度预留的服务方案:请求长度和生命周期未知,会带来未用预留、末尾内部碎片与 allocator 外部碎片。PagedAttention 把 KV Cache 切成固定大小 block,用块表把“逻辑 token 块”映射到“不连续物理显存块”,随序列增长按需分配。
这是一张机制示意,不是操作系统虚拟内存的逐项复刻:block table 提供地址间接层,但 PagedAttention 本身不等同于 demand paging、page fault 或磁盘换页;抢占时选择重算、CPU swap 或远端 KV transfer 是服务系统的另一层策略。
常规自回归 decode 中,每条活跃序列每轮通常推进 1 个 token;投机解码等实现可以一次接受多个。若活跃序列太少,GPU 容易受权重与 KV 搬运限制。Continuous batching(连续批处理,也叫 iteration-level scheduling)在迭代边界动态组成 batch:完成的序列移出,符合准入条件的新工作补入。
| 调度方式 | 问题 | 连续批处理怎么改 |
|---|---|---|
| 静态 batch | 等一批请求全部结束再换下一批;短请求会等长请求。 | 每个 iteration 都能插入/移除请求。 |
| 只看吞吐 | batch 太大时 TTFT/TPOT 可能恶化。 | 按 SLO 控 batch、prefill chunk 和队列优先级。 |
| 忽略 KV | 请求塞太多导致 KV Cache 爆显存。 | PagedAttention + admission control 一起决定能塞多少。 |
KV Cache 不是只有 decode 才重要。RAG、多轮对话、Agent 常有大量共享前缀或超长 prompt,prefill 会抢算力并阻塞 decode。现代推理系统会专门拆这块。
| 技术 | 解决什么 | 机制 |
|---|---|---|
| Prefix Cache | 同一长文档、多轮历史或 few-shot 前缀反复 prefill | 缓存完整 KV block;新请求在 token IDs、前缀父 hash 和引擎要求的模型/adapter/多模态等附加身份一致时复用。它跳过命中部分的 prefill,不改变后续新 token 的 dense decode 数学。 |
| Chunked Prefill | 一个超长 prompt 占住 GPU,短 decode 被饿死 | 把 prefill 切成小块,与 decode iteration 混批或交错;chunk / token budget 会在 TTFT、TPOT 与吞吐之间取舍。 |
| Prefill/Decode 分离 | prefill 常更偏算力、decode 在低 batch 时常更偏带宽,混跑会互相干扰 | 把 prefill worker 和 decode worker 分开并独立扩缩容;需要额外传 KV,未必对所有负载更快。 |
| KV Transfer | PD 分离后,KV 要跨 GPU/节点搬 | 用高速互联和调度策略减少 KV 传输成为新瓶颈。 |
若模板把同一长文档放在查询之前,使多个请求拥有相同 token ID 前缀,Prefix cache 命中后可跳过已缓存的完整 block;未满末块、文档顺序、空格、工具列表或查询插入位置变化都可能减少命中。
长任务会反复带着系统提示、工具说明、历史轨迹调用模型。KV 复用和上下文压缩都会直接影响成本。
错。KV Cache 相比重算完整前缀确实大幅降低总计算,但第 t 个新 token 的 query 仍要读约 t 个历史 K/V;标准全注意力的累计增量 attention 仍是二次量级。
不会。它主要减少预留、碎片和可共享前缀的重复物理副本;每 token 元素数或位宽要靠 GQA/MLA/KV quant 等改变。
FlashAttention 优化一次 attention 算子的 IO;KV Cache 处理历史状态生命周期。两者职责不同,但可以组合在同一个 KV-aware / paged decode kernel 中。
窗口变长不等于召回变好;长上下文还会提高 KV 成本、调度难度和延迟。
吞吐高可能靠大 batch 换来,但 TTFT/TPOT 可能变差。服务要看 SLO,不只看 tokens/s。
可复用块需要相同 token 前缀,并满足模型、adapter、多模态输入等引擎校验条件;模板、空格、工具列表顺序变化都可能影响命中。
| KV Cache 是什么 | 每层 attention 缓存历史 token 的 K/V,避免每步重算历史。 |
| 为什么爆显存 | 随 batch、层数、上下文长度、KV 头数、head_dim、dtype 线性增长。 |
| PagedAttention 是什么 | 用固定大小 block 与块表管理 KV,减少预留与碎片,并为块级共享提供机制;不是完整复刻 OS demand paging。 |
| Continuous batching | 在 iteration 边界动态组 batch,让一次 decode step 推进更多活跃序列。 |
| 真正减少 KV 状态 | GQA/MQA/MLA 改元素数,KV quant 改位宽,滑窗/稀疏改变保留或访问范围;上下文压缩则会改变输入历史本身。 |
| 下一层专题 | 量化、MoE、分布式训练都会继续围绕“容量、带宽、通信”展开。 |
核查日期:2026-07-14。显存手算采用二进制 KiB/GiB;实际占用还受 KV dtype、张量/上下文/流水并行布局、prefix sharing、block 大小、对齐、元数据、缓存实现和同时驻留序列长度分布影响。