Causal Attention:为什么 KV hit 后 Attention 按 1 - h² 缩放
1. 先把 causal attention 想成一个下三角
这里说的是 causal attention,也就是自回归模型里的注意力约束:第 i 个 token 只能看 1..i 这些历史 token,不能看未来 token。
假设输入有 N 个 token:
token: 1 2 3 4 5 ... N
在 prefill 阶段,模型一次性处理整个 prompt。每个 token 的 attention 工作量大概是:
第 1 个 token 看 1 个
第 2 个 token 看 2 个
第 3 个 token 看 3 个
...
第 N 个 token 看 N 个
总量近似是:
1 + 2 + 3 + ... + N = N(N+1)/2 ≈ N² / 2
所以 prefill attention 的核心成本更接近二次方级别,而不是线性级别。
把它画成矩阵,就是一个下三角区域:
key/value token
1 2 3 4 5 6 7 8
query
1 x
2 x x
3 x x x
4 x x x x
5 x x x x x
6 x x x x x x
7 x x x x x x x
8 x x x x x x x x
每个 x 表示一次 query token 对 key/value token 的 attention 交互。整个 prefill attention 大概就是这个下三角面积。
2. KV hit 省掉的是 prefix-prefix 区域
现在假设 KV cache hit 了前 hN 个 prefix。以 N=8、前 4 个 token hit 为例:
prefix hit: 1 2 3 4
miss suffix: 5 6 7 8
prefix 内部这块已经有缓存,不需要重算:
1 2 3 4 | 5 6 7 8
1 .
2 . .
3 . . .
4 . . . .
-------------------------
5 x x x x | x
6 x x x x | x x
7 x x x x | x x x
8 x x x x | x x x x
关键点是:虽然前 4 个 token hit 了,但后面的 suffix token 5,6,7,8 仍然要 attend 到前面的 prefix token。因为 token 5 的表示依赖 token 1..5,token 8 的表示依赖 token 1..8。
所以 KV hit 省掉的不是“前 hN 个 token 的线性计算量”,而是 prefix-prefix 这块二维三角区域。剩下的 attention 工作量由两部分组成:
- suffix 对 prefix 的 attention:矩形区域
M * H - suffix 内部的 causal attention:三角区域
M² / 2
其中:
H = hN // hit prefix 长度
M = (1-h)N // miss suffix 长度
3. 公式为什么是 1 - h²
剩余 attention work 约为:
M * H + M² / 2
原始 0-hit 全量 prefill attention work 约为:
N² / 2
两者相除,得到相对工作量:
(M * H + M² / 2) / (N² / 2)
= 2MH/N² + M²/N²
= 2h(1-h) + (1-h)²
= 1 - h²
因此在 KV cache hit ratio 为 h 时,attention bucket 常用的一阶近似是:
T_attn(h) = T_attn0 * (1 - h²)
这个公式表达的是:KV hit 后,attention 省掉的是 prefix-prefix 的二维区域;但 suffix 仍然要看 cached prefix,所以 attention 成本下降慢于 1-h。
4. 和 FFN 的线性缩放有什么区别
FFN / MLP / MoE / 大部分 GEMM 更接近逐 token 独立计算。prefix hit 之后,hit 的 token 不需要重新跑 FFN,miss 的 suffix token 需要跑,所以它们更接近线性缩放:
T_ffn(h) = T_ffn0 * (1 - h)
Attention 不同,因为一个 suffix token 的 attention 输入不仅包括 suffix 内部,也包括 cached prefix。它仍然要和 prefix 的 K/V 发生交互。
举个数值例子,h = 0.5,一半 prefix hit:
FFN / GEMM 类线性部分:剩 1 - h = 50%
Attention 部分:剩 1 - h² = 75%
也就是说,命中一半 prefix,并不代表 attention 只剩一半,因为后半段 token 仍然要看前半段 prefix。
5. 放到仿真器里应该怎么用
对 KV cache hit ratio 做 prefill TTFT 修正时,可以先把 0-hit TTFT 拆成几类:
TTFT0 = T_attn0 + T_ffn0 + T_comm0 + T_other0
一个可解释的一阶模型是:
TTFT_compute(h) = T_attn0 * (1 - h²)
+ T_ffn0 * (1 - h)
+ T_comm0
+ T_other0_fixed
含义是:
- attention bucket 按二维 causal attention 剩余区域缩放。
- FFN / MoE / GEMM 按 miss token 数线性缩放。
- communication / dispatch / runtime 这类固定开销保守不缩放。
如果还要模拟 KV cache 从存储池或 Host 加载到 GPU HBM 的成本,还需要再加 transfer term:
T_load(h) = h * ISL * S_kv_per_gpu / B_transfer
TTFT(h) = T_fixed
+ T_load(h)
+ T_compute_var(h)
- overlap_ratio * min(T_load(h), T_compute_var(h))
这里的 overlap_ratio 用来表示 KV load 和 miss-token compute 能重叠多少:
0:完全不重叠,偏线上复刻口径。1:充分重叠,偏仿真优化目标口径。
6. 这个近似的边界
1 - h² 不是逐 kernel 精确公式,它适合解释和估算 attention bucket 的主要趋势。使用时要注意几个边界:
- 如果 breakdown 能把 QKV projection、O projection 和真正的 FlashAttention 分开,那么 projection 更接近
1-h,不应该强行放进1-h²。 - 如果模型使用 sliding window、sparse attention、CSA/HCA、MLA 等机制,attention 的可见区域不再是标准 dense causal 下三角,缩放函数需要按实际可见区域重算。
- 如果 kernel 是 memory-bound,延迟不一定严格等于理论交互数量缩放;实际还会受 HBM、cache locality、kernel launch、batch shape 影响。
- 如果 KV cache 存在外部存储池,attention compute 下降不代表 TTFT 一定下降;高 hit ratio 下可能转为 KV load 带宽受限。
7. 一句话记忆
Causal attention 的 prefill 成本像一个下三角面积。KV hit 省掉的是 prefix-prefix 的三角区域,剩下的 suffix 仍然要看 prefix,所以 attention 剩余成本近似是
1 - h²,而不是1 - h。
相关页面
← 被以下页面引用(1)
- Chunked Prefill 深入分析:调度、Chunk Size 与 Attention 形状ai-systems · synthesis
修改历史2 次提交
- feat(wiki): connect core topics and add reading seriesxiaocheng··
e947096 - docs: add inference profiling notesxiaocheng··
6a94c5d