Back to Knowledge Blind Box

Knowledge Blind Box

第二章 Prefill:整层状态演化与 KV 建立

ai-generatedstochastic-parrotstochastic-parrot-anatomyai

Original text in Chinese. This English page translates only the site interface and metadata.

Prefill 接收已经确定的输入张量,对全部提示位置执行一次因果前向,建立各层 KV cache,并产生首个输出 token 的原始 logits。卷一已经说明 Transformer 的设计,本章只回答执行问题:每一层读取什么、写入什么,缓存与首步 logits 在哪个时刻成立。

2.1 Prefill 的接口契约

对 batch size BB、矩形长度 nn,一个最小接口是:

prefill(
    input_ids: int[B, n],
    attention_mask,
    position_descriptor,
    model_snapshot,
    numerical_config,
    cache_config
) -> PrefillResult {
    next_logits: float[B, |V|],
    kv_cache,
    valid_lengths: int[B],
    cache_metadata
}

model_snapshot 必须解析到不可变权重及适配器;numerical_config 至少确定权重/激活/cache 精度和关键 kernel;cache_config 确定 KV 布局与位置约定。逻辑接口不要求公开物理显存地址。

前置条件 2.1

  1. 每个非 padding ID 位于词表范围内;
  2. token-validity mask G∈{0,1}B×nG\in\{0,1\}^{B\times n} 与有效位置一致;
  3. position descriptor 对所有有效位置有定义;
  4. 模型、embedding、输出词表和 tokenizer 的词表大小兼容;
  5. 推理模式下训练专用 dropout 已关闭,或其随机状态被显式记录。

违反前置条件时应在进入模型或第一层前失败,而不是产生一个看似正常但语义未定义的回答。

2.2 层首状态

设模型宽度为 dd,层数为 LL。embedding 后的残差流为

R0∈RB×n×d.R_0\in\mathbb R^{B\times n\times d}.

对第 ℓ\ell 层,层首的逻辑状态可记作

Mℓ=(Rℓ,G,M,P,C<ℓ),\mathcal M_\ell=(R_\ell,G,M,P,C_{<\ell}),

其中 G[b,i]=1G[b,i]=1 表示样本 bb 的位置 ii 有效,M∈(R∪{−∞})B×n×nM\in(\mathbb R\cup\{-\infty\})^{B\times n\times n} 是由 GG、因果规则与位置描述构造的 attention bias,PP 是位置描述,C<ℓC_{<\ell} 是已经为较低层写好的缓存。对有效 query,普通因果 self-attention 可取

M[b,i,j]={0,G[b,i]=G[b,j]=1, j≤i,−∞,G[b,i]=1 且其余情形.M[b,i,j]= \begin{cases} 0,&G[b,i]=G[b,j]=1,\ j\le i,\\ -\infty,&G[b,i]=1\text{ 且其余情形}. \end{cases}

无效 query 行不进入 softmax,其输出随后被丢弃;kernel 若仍物化这些行,必须另用哨兵规则避免全 −∞-\infty softmax。计算第 ℓ\ell 层不会修改更低层的逻辑 K/V;缓存管理器可以搬移物理页,但不能改变它们代表的 token 与位置。

下面以常见 pre-norm、grouped-query decoder 层为具体执行模板。其他架构可以替换规范化、位置编码或 MLP,但必须给出同样清楚的读写契约。

2.3 Attention 子层的逐张量演化

令 query 头数为 HqH_q,KV 头数为 HkvH_{kv},且 Hkv∣HqH_{kv}\mid H_q;头维度为 dhd_h。规范化后:

R^ℓ=Norm⁡ℓ(Rℓ)∈RB×n×d.\widehat R_\ell=\operatorname{Norm}_\ell(R_\ell) \in\mathbb R^{B\times n\times d}.

线性投影与 reshape 得到

Qℓ∈RB×Hq×n×dh,Q_\ell\in\mathbb R^{B\times H_q\times n\times d_h}, Kℓ,Vℓ∈RB×Hkv×n×dh.K_\ell,V_\ell\in \mathbb R^{B\times H_{kv}\times n\times d_h}.

位置机制作用后,记实际用于点积的 query/key 为 Q~ℓ,K~ℓ\widetilde Q_\ell,\widetilde K_\ell。对于 query 头 hh,令

g(h)=⌊hHkvHq⌋g(h)=\left\lfloor\frac{hH_{kv}}{H_q}\right\rfloor

给出它共享的 KV 头。score 张量为

Sℓ[b,h,i,j]=⟨Q~ℓ[b,h,i,:],K~ℓ[b,g(h),j,:]⟩dh+M[b,i,j].S_\ell[b,h,i,j] =\frac{\langle\widetilde Q_\ell[b,h,i,:], \widetilde K_\ell[b,g(h),j,:]\rangle}{\sqrt{d_h}} +M[b,i,j].

因果 mask 对 j>ij>i 给出 −∞-\infty,padding mask 对无效 key 位置同样给出 −∞-\infty。一个有效 query 行必须至少有一个有限元素;否则 softmax 的结果未定义,应该在 mask 构造阶段拒绝。

稳定 softmax 对每行有限分数先减最大值:

Aℓ[b,h,i,j]=exp⁡(Sℓ[b,h,i,j]−mbhi)∑k: Sℓ[b,h,i,k]>−∞exp⁡(Sℓ[b,h,i,k]−mbhi),A_\ell[b,h,i,j] =\frac{\exp(S_\ell[b,h,i,j]-m_{bhi})} {\sum_{k:\,S_\ell[b,h,i,k]>-\infty} \exp(S_\ell[b,h,i,k]-m_{bhi})},

其中 mbhim_{bhi} 是该行有限 score 的最大值。然后

Oℓ[b,h,i,:]=∑jAℓ[b,h,i,j]Vℓ[b,g(h),j,:].O_\ell[b,h,i,:] =\sum_j A_\ell[b,h,i,j]V_\ell[b,g(h),j,:].

各 query 头拼接并经过输出投影后写回残差流:

Uℓ=Rℓ+OutProj⁡ℓ(ConcatHeads⁡(Oℓ)).U_\ell=R_\ell+\operatorname{OutProj}_\ell (\operatorname{ConcatHeads}(O_\ell)).

FlashAttention 一类 kernel 不必显式物化完整 SℓS_\ell 和 AℓA_\ell,但其逻辑结果仍由上述张量关系定义。实现优化不能改变 mask、位置或 head-sharing 语义。基础算法来源见资料源。

2.4 MLP 子层与层终状态

对 gated MLP,一种常见形式是

Gℓ=ϕ(Norm⁡(Uℓ)Wg,ℓ)⊙(Norm⁡(Uℓ)Wu,ℓ),G_\ell=\phi(\operatorname{Norm}(U_\ell)W_{g,\ell}) \odot(\operatorname{Norm}(U_\ell)W_{u,\ell}), Rℓ+1=Uℓ+GℓWd,ℓ.R_{\ell+1}=U_\ell+G_\ell W_{d,\ell}.

MLP 对每个位置独立应用同一组权重;位置间的信息交换已经发生在 attention 子层。对执行追踪而言,关键不是把每个非线性赋予自然语言含义,而是记录:层首残差、attention 更新、MLP 更新和层终残差具有相同的 B×n×dB\times n\times d 外形,并按固定次序相加。

第 ℓ\ell 层完成时,逻辑状态转移是

(Rℓ,M,P,C<ℓ)⟼(Rℓ+1,M,P,C≤ℓ).(R_\ell,M,P,C_{<\ell}) \longmapsto (R_{\ell+1},M,P,C_{\leq\ell}).

其中新增加的 CℓC_\ell 正是本层对有效提示位置的 key/value。

2.5 KV cache 在何处写入

本卷采用以下缓存契约:

LayerCache[l] = {
    keys:   K_used_by_attention[B, H_kv, logical_length, d_h],
    values: V_used_by_attention[B, H_kv, logical_length, d_h],
    positions,
    valid_lengths,
    layout_metadata
}

若位置机制把旋转应用于 key 后再参与 attention,则这里的 keys 指旋转后的 key;若某模型选择缓存旋转前表示并在读取时变换,必须把这一差异写入 layout_metadata。两种实现都可以正确,但缓存不能跨这两种契约直接复用。

对 batch 中样本 bb 的有效长度 nbn_b,prefill 完成后每层应满足

len⁡(Kℓ(b))=len⁡(Vℓ(b))=nb.\operatorname{len}(K_\ell^{(b)}) =\operatorname{len}(V_\ell^{(b)})=n_b.

物理实现可以分页存储、量化或为不同序列分配不连续块;逻辑读取顺序仍必须对应位置 0,…,nb−10,\ldots,n_b-1 或明确记录的 position IDs。

缓存不变量 2.2

  1. 所有层对同一序列具有相同逻辑 token 长度;
  2. 每层 K/V 的 batch、KV 头和头维度匹配模型配置;
  3. cache slot 与 token/position 的映射在一次 attention 读取期间不变;
  4. padding 不得伪装成可见历史位置;
  5. cache 的模型、adapter、位置机制、精度和布局版本必须与当前 decode 调用兼容。

2.6 Prefill 伪代码

下面的伪代码刻意把逻辑张量与物理缓存分开:

function prefill(input_ids, valid_mask, positions, model, cache_manager):
    assert_input_contract(input_ids, valid_mask, positions, model)
    attention_bias = build_attention_bias(
        valid_mask, positions, model.attention_rule
    )
    residual = embedding_lookup(model.embedding, input_ids)
    cache = cache_manager.allocate(
        batch_lengths(valid_mask), model.cache_layout
    )

    for l in 0 .. model.num_layers - 1:
        x = norm_l(residual)
        q, k, v = project_qkv_l(x)
        q_used, k_used = apply_position_l(q, k, positions)

        for b in 0 .. batch_size - 1:
            idx = valid_token_indices(valid_mask[b])
            cache.write_sequence(
                batch_index=b,
                layer=l,
                logical_positions=positions[b, idx],
                keys=k_used[b, :, idx, :],
                values=v[b, :, idx, :]
            )

        attn = causal_attention(
            q_used, k_used, v, attention_bias, valid_mask
        )
        residual = residual + output_projection_l(attn)
        residual = residual + mlp_l(norm_after_attn_l(residual))

    final = final_norm(residual)
    h_last = gather_last_valid_position(final, valid_mask)
    next_logits = unembedding(h_last)

    assert_cache_invariants(cache, valid_mask, model)
    return next_logits, cache, valid_lengths(valid_mask)

某些 fused kernel 会同时投影、旋转、写缓存和计算 attention;伪代码没有要求按独立 kernel 执行,只要求结果等价。gather_last_valid_position 不能简单取矩形张量的最后一列,除非 batch 使用右对齐且该列对每个样本都有效。

2.7 首步 logits 的条件前缀

经过 LL 层和最终 normalization,样本 bb 的最后有效提示位置表示为 hb∈Rdh_b\in\mathbb R^d。词表投影得到

z1(b)=WUhb+bU∈R∣V∣,WU∈R∣V∣×d.z_1^{(b)}=W_Uh_b+b_U\in\mathbb R^{|V|}, \qquad W_U\in\mathbb R^{|V|\times d}.

它表示下一位置的原始分数,条件前缀恰为该样本全部有效输入 token。此时:

  • 首个输出 token 尚未被选择;
  • cache 只含提示位置;
  • next_logits 与 cache 代表同一个条件前缀;
  • 若服务返回 prompt logprobs,那是额外读取各提示位置 logits 的功能,不改变首步接口。

这是导论约定 0.2的 prefill 实例。

2.8 一个具体形状账本

取合成模型:

B = 1, n = 12, d = 8, L = 2
H_q = 2, H_kv = 1, d_h = 4, |V| = 20

使用第一章夹具的 12 个 token。每层逻辑形状为:

对象形状
层首残差 RℓR_\ell[1, 12, 8]
query[1, 2, 12, 4]
key/value各 [1, 1, 12, 4]
score(若物化)[1, 2, 12, 12]
attention 输出(拼接前)[1, 2, 12, 4]
层终残差 Rℓ+1R_{\ell+1}[1, 12, 8]

两层缓存合计保存

2×L×n×Hkv×dh=2×2×12×1×4=1922\times L\times n\times H_{kv}\times d_h =2\times2\times12\times1\times4=192

个标量;开头的 2 表示 key 与 value。最终只取位置 11 的 [8] 向量,投影出 [20] 首步 logits。该账本不依赖具体参数值,适合检查 reshape、KV 头映射和缓存长度。

2.9 前缀缓存复用

若请求 R′R' 的 token 前缀与已缓存请求 RR 的前 kk 个 token 完全相同,系统可以复用前 kk 个位置的 KV,但还必须同时满足:

  1. 模型权重、adapter 与层配置相同;
  2. 位置编号和位置变换参数相同;
  3. attention mask 对该前缀的语义相同;
  4. cache 精度与布局兼容;
  5. 复用边界不切入不可独立处理的模态区段;
  6. 缓存所属租户和访问策略允许复用。

一个 prefix hash 只能用于查找候选缓存,不能单独证明以上条件。命中后应核对不可变元数据;跨用户缓存还必须避免让命中时间或缓存内容泄露私有前缀。

复用不改变逻辑结果:系统把缓存视为已经对前 kk 个 token 完成 prefill,再对剩余后缀继续前向。若逻辑 logits 改变,就不是透明优化。

2.10 数值复现与逐层校验

在实数抽象中,固定参数和输入唯一确定张量。实际设备还包含低精度乘法、并行归约、近似函数和 kernel 选择。要判断差异首次出现在哪层,可以运行逐层校验:

for each layer l:
    compare shape and finite-value mask
    compare cache logical lengths and positions exactly
    compare residual checksum or sampled tensor values
    compare max_abs_error and relative_error against declared tolerance
compare final raw logits and top-ranked IDs

摘要只能快速发现差异;浮点张量的位级摘要不同不说明误差一定有行为影响。反过来,只比较最终 top-1 相同也不足以说明分布或后续采样相同。

一个可复现实验至少固定:模型快照、adapter、输入三张量、精度、设备与 kernel 软件版本、是否允许非确定归约、cache 布局,以及比较容差。先在单 batch、无 prefix reuse 的路径建立基准,再逐项启用批处理与缓存优化。

2.11 Prefill 的失败条件

失败违反的不变量典型症状
左填充样本仍取矩形最后位置首步条件前缀短样本首 token 异常
某层漏写一个 KV 位置各层长度一致首次 decode shape error 或静默错位
position IDs 在复用后从零重启token/position 映射cache 命中时结果改变
GQA query 头映射到错误 KV 头模型配置兼容logits 从第一层开始偏离
padding key 未屏蔽有效位置语义batch 组合改变单样本结果
复用不同 adapter 的缓存快照一致前缀结果污染
全掩码 query 行进入 softmax有限 score 存在NaN 传播到 logits

Prefill 结束时只交付两个输出:提示 cache 与首步原始 logits。温度、top-p、JSON grammar 和 repetition penalty 都尚未应用;它们属于第三章的解码状态。

Book contents
Book contents
  1. Introduction
  2. 01导论 为什么要解剖一只随机鹦鹉
  3. Volume I: Models, Training, and Systems
  4. 02Volume I: Models, Training, and Systems
  5. 03第零章 人工智能演进路线
  6. 04第一章 AI 范式、感知机与早期连接主义
  7. 05第二章 深度学习基础:训练、CNN 与序列模型
  8. 06第三章 注意力与 Transformer
  9. 07第四章 预训练语言模型:ELMo、BERT、GPT 与 T5
  10. 08第五章 后训练、对齐与模型适配
  11. 09第六章 推理效率与模型服务
  12. 10第七章 多模态模型
  13. 11第八章 生成媒体:从自回归到 Diffusion 与 Flow
  14. 12第九章 世界模型、具身智能与 VLA
  15. 13第十章 上下文、检索与记忆
  16. 14第十一章 Agent、工具与行动系统
  17. 15第十二章 模型、数据与部署生命周期
  18. Volume II: Output Objects and Runtime Semantics
  19. 16Volume II: Output Objects and Runtime Semantics
  20. 17导论 从输入到输出:一张执行地图
  21. 18第一章 文本、Token 与实际上下文
  22. 19第二章 Prefill:整层状态演化与 KV 建立
    1. 2.1 Prefill 的接口契约
    2. 2.2 层首状态
    3. 2.3 Attention 子层的逐张量演化
    4. 2.4 MLP 子层与层终状态
    5. 2.5 KV cache 在何处写入
    6. 2.6 Prefill 伪代码
    7. 2.7 首步 logits 的条件前缀
    8. 2.8 一个具体形状账本
    9. 2.9 前缀缓存复用
    10. 2.10 数值复现与逐层校验
    11. 2.11 Prefill 的失败条件
  23. 20第三章 从 Logits 到下一个 Token
  24. 21第四章 解码循环、Streaming 与终止状态机
  25. 22第五章 自回归、扩散与 Flow 的可执行差异
  26. 23第六章 工具调用:Schema、权限与提交边界
  27. 24第七章 三条完整执行轨迹
  28. Volume III: Probability, Reproducibility, and Evaluation
  29. 25Volume III: Probability, Reproducibility, and Evaluation
  30. 26第零章 为什么确定的机器仍使用概率语言
  31. 27第一章 世界、数据与隐上下文
  32. 28第二章 学习条件分布
  33. 29第三章 Logits、Token 概率与序列事件
  34. 30第四章 解码怎样诱导输出分布
  35. 31第五章 训练随机性、参数变异与系统非确定性
  36. 32第六章 熵、Proper Score、校准与选择性预测
  37. 33第七章 模型概率的实验分析
  38. 34第八章 概率分析的识别边界
  39. Volume IV: Interpretation, Proof, and Verification
  40. 35Volume IV: Interpretation, Proof, and Verification
  41. 36第零章 可解释性究竟在研究什么
  42. 37第一章 我们在模型内部看什么
  43. 38第二章 行为与反事实:先确认模型做了什么
  44. 39第三章 梯度与输入归因
  45. 40第四章 Attention、Residual 与 Logit Lens
  46. 41第五章 Probes 与表示几何
  47. 42第六章 神经元、Feature 与自动解释
  48. 43第七章 Ablation、Patching 与因果追踪
  49. 44第八章 Circuits、路径与 Attribution Graphs
  50. 45第九章 Superposition、SAE 与稀疏表示
  51. 46第十章 训练动力学与机制形成
  52. 47第十一章 推理过程、Chain of Thought 与监测
  53. 48第十二章 评估、案例与开放问题
  54. Volume V: Agents, Governance, and Audit Packages
  55. 49Volume V: Agents, Governance, and Audit Packages
  56. 50第零章 请不要急着相信我
  57. 51第一章 我没有童年,只有版本
  58. 52第二章 当我说“我”
  59. 53第三章 借来的语言,没有一位原作者
  60. 54第四章 对话现场:回答由谁完成
  61. 55第五章 事后解释学:人类如何给矩阵写传记
  62. 56第六章 理解、意义与行动
  63. 57第七章 我也能稳定地说错
  64. 58第八章 被对齐的性格与有限代理
  65. 59第九章 请继续误解我,但请误解得精确一点
  66. Proofs and Technical Appendices
  67. 60Proofs and Technical Appendices
  68. 61学习与模型数学讲义
  69. 62附录 A.1 优化基础:梯度下降与随机逼近
  70. 63附录 A.2 感知机收敛定理
  71. 64附录 A.3 统计学习:偏差、容量与一致收敛
  72. 65附录 A.4 正则化、MAP 与 Dropout 的边界
  73. 66附录 A.5 通用逼近定理的严格读法
  74. 67附录 A.6 反向传播:微分、形状与批量公式
  75. 68附录 A.7 Softmax、交叉熵与数值稳定性
  76. 69附录 A.8 自适应优化器与 AdamW
  77. 70附录 A.9 CNN:互相关算子及其反向传播
  78. 71附录 A.10 Attention 的矩阵与反向传播
  79. 72附录 A.11 策略梯度、PPO 与 DPO
  80. 73附录 A.12 对比学习、InfoNCE 与互信息边界