Skip to content

第九章 Prefill 与 Decode 计算量

本章计算矩阵乘法的主项,统一按一次乘加 2 FLOPs。Norm、Softmax、RoPE、激活函数、路由选择、采样和数据搬运并未被这些矩阵公式完整覆盖;它们参数少,却可能影响实际耗时。

1 线性层为什么近似是 2P

对一个 token,$[1,a]\times[a,b]$ 的每个输出元素需要约 $a$ 次乘加;一共 $b$ 个输出,因此是 $2ab$ FLOPs。矩阵有 $ab$ 个参数,所以一次使用它约为 2 倍参数量。

将各 block 实际执行的线性层参数加起来,记为 $P_{\rm lin}$。对 Dense SwiGLU、$d_q=d$:

$$ P_{\rm lin}=L(2d^2+2dd_{kv}+3dm) $$

对同构 MoE,无共享专家:

$$ P_{\rm lin}=L(2d^2+2dd_{kv}+3kdm_e+dE) $$

$n$ 个 token 的 block 线性层计算约为 $2nP_{\rm lin}$。这排除了输入 Embedding 查表,并把 LM Head 单独处理;也还没有算 Attention 的 QK 和 AV。

“每 token 约 $2P$”只适合线性权重主导的粗略估计。长上下文、超大词表、MoE、权重共享或反复复用模块时,都要回到实际算子。

2 完整 Prefill 的注意力

对每个 Q head,$QK^\top$ 为 $2S^2d_h$ FLOPs,$AV$ 同样如此;乘上 batch、head 数和层数:

$$ F_{\rm attn,prefill,full}=4LBh_qd_hS^2=4LBd_qS^2 $$

这是按完整方阵计算的口径。因果注意力真正合法的 query-key 配对只有:

$$ 1+2+\cdots+S=\frac{S(S+1)}{2} $$

每对在 QK 与 AV 中合计约 $4d_h$ FLOPs,因此理想跳过无效三角区域时:

$$ F_{\rm attn,prefill,causal}=2LBd_qS(S+1) $$

实际 kernel 按 tile 工作,还可能计算部分被 mask 的位置,因此不能只看到 causal mask 就宣称硬件实际工作量严格减半。回答时可以同时给出完整方阵口径和因果有效工作量口径,并说明使用哪个。

3 Prefill 总 FLOPs 与输出层

若只对每条 prompt 最后一个位置计算 logits:

$$ \boxed{F_{\rm pre}\approx2BSP_{\rm lin}+2LBd_qS(S+1)+2BdV} $$

如果对所有 prompt 位置计算 logits,则末项变成 $2BSdV$。这可能出现在训练、需要所有位置 logprobs 或某些实现中。LM Head 的权重是否绑定不影响此处 FLOPs。

变长 batch 不应盲目用最大 $S$ 乘 $B$。在能去掉 padding 计算的实现中,线性项按 $\sum_iS_i$,注意力项按 $\sum_iS_i(S_i+1)$;如果 kernel 真的计算 padding,则要按实际执行形状计费。

4 带缓存前缀的 chunked Prefill

已有 $T$ 个前缀 token 的 KV,本次追加 $C_t$ 个已知输入 token。第 $j$ 个新 query 可以读取 $T+j$ 个 key,因此合法配对数为:

$$ C_tT+\frac{C_t(C_t+1)}{2} $$

相应的理想有效注意力 FLOPs 为:

$$ 4LBd_q\left(C_tT+\frac{C_t(C_t+1)}{2}\right) $$

线性层只处理 $BC_t$ 个新 token。前缀缓存复用免去了旧 token 的重新投影和旧位置的 Attention,但新 query 对旧前缀的读取与注意力仍然存在。

把无缓存 prompt 拆成多个 chunk,并不会自动改变所有合法配对的总数;收益主要来自调度、峰值显存和延迟安排,代价可能包括重复读取与更多调度开销。

5 一个 Decode step

step 开始前有 $T$ 个旧 token,本次处理一个新输入 token。新 Query 读取 $T+1$ 个 K/V,包括当前位置:

$$ F_{\rm attn,dec}=4LBd_q(T+1) $$

加上线性层与每序列一次 LM Head:

$$ \boxed{F_{\rm dec,step}\approx2BP_{\rm lin}+4LBd_q(T+1)+2BdV} $$

一个 step 总计产出 $B$ 个预测 token,因此平均每输出 token 的主项是上述数值除以 $B$。这里不包含推测解码一次验证多个候选 token 的情况。

固定模型下,线性项与 $T$ 无关,Attention 项随 $T$ 线性增长。所以“Decode 每 token 固定 2P”会低估长上下文成本。

6 一整段生成

若 Prefill 输入长度为 $S$,要生成 $N$ 个输出 token,后续有 $N-1$ 次 Decode。第 $j$ 次 Decode 看到 $S+j$ 个 key,$j=1,\ldots,N-1$。

线性层和 LM Head 的主项是:

$$ 2B(N-1)(P_{\rm lin}+dV) $$

Decode 注意力总量是:

$$ 4LBd_q\left((N-1)S+\frac{N(N-1)}{2}\right) $$

再加 Prefill 即得请求计算主项。输出长度增大时,不仅步数增多,每步看到的上下文也逐渐变长。

7 什么时候 Attention 计算显著

在单序列 Decode 中,忽略输出层,用 $2P_{\rm lin}=4LdT$ 求两项相等的上下文长度:

$$ T_{\rm equal}\approx\frac{P_{\rm lin}}{2Ld} $$

这是 FLOPs 的交点,不是耗时的交点。Attention 可能在 FLOPs 仍较小时,就因为 KV 带宽成为延迟瓶颈。

Prefill 的线性项随 $S$ 增长,注意力项随 $S^2$ 增长;Decode 每步只有一个新 Query,因此其注意力是 $O(T)$。若没有 KV Cache,每一步都重新处理整个前缀,才会重复支付大量前缀计算。

8 训练 FLOPs 的边界

对大矩阵乘法,反向传播通常还要计算输入梯度和权重梯度,所以前向加反向粗略约为前向的三倍,形成常见的每训练 token 约 $6P$ 估算。它仍是权重主导近似:注意力、重计算、输出层、稀疏路由和优化器步骤应按需要另计。不要把 $6P$ 用于普通推理解码。

下一章:吞吐与延迟估算。