DeepSeek V4.1 的 KV Cache 汇总:改了什么、HCA 为什么退场、CED+CSA2 复现实测
汇总篇:第 1 章取自《DeepSeek-V4.1-Flash推理加速解读》——V4.1-Flash 改了什么(四步递进的推理配置)与量化的效果账;第 2、3 章讲 KV Cache 从 MLA 基准到 V4.0 三段分段再到 V4.1 换路径的演进史与 HCA 废弃的相位根因;第 4、5 章是训练结构说明与 Qwen3.5-4B 复现实测。素材:Flash 解读、kv演进.md、复现实测.md、out/ 训练结构图 ×2、相位敏感性一篇
目录
1 V4.1-Flash 改了什么:一句话与四笔账
2 KV Cache 演进:MLA → V4.0 三段分段 → V4.1 换路径
3 HCA 为什么退场:无重叠的相位代价
4 训练说明:老师-学生结构与三段关键代码
5 复现实测:设定、结果与边界
6 结论与素材索引
1. V4.1-Flash 改了什么:四步递进与量化效果账
固有瓶颈 (该篇的出发点):Transformer 每一层都独立保存专属 K、V——层数与序列长一起乘,上下文一长 KV Cache 先爆。V4.1-Flash 的解法不是继续把每一份压小,而是动「谁生成、谁持有」。
架构总览 :40 层主干切成两段——前 20 层因果编码器 + 后 20 层解码器,每层内含 MoE 路由(Prefill 激活 8B/token);两段之间靠 KV 投影 衔接:解码器的全局 KV 不从自身生成,而由编码器最后一层隐藏态 H_20 投射得到。
flowchart TD
classDef io fill:#f6f8fa,stroke:#8b949e,color:#1f2328,stroke-width:1.5px
classDef enc fill:#ddf4ff,stroke:#0969da,color:#0969da,stroke-width:1.5px
classDef dec fill:#fbefff,stroke:#8250df,color:#8250df,stroke-width:1.5px
classDef proj fill:#fff,stroke:#d0d7de,color:#59636e,stroke-dasharray:4 3
IN["输入 tokens 文本 + 图像"]:::io
subgraph ENC["因果编码器 · 20 层"]
direction TB
E1["层 1–20 每层内含 MoE 路由 Prefill 激活 8B/token"]:::enc
end
PROJ["KV 投影 每层独立投射权重 不涉及注意力 / MoE"]:::proj
subgraph DEC["解码器 · 20 层"]
direction TB
D1["层 21–40 每层内含 MoE 路由 Decode 激活 16B/token"]:::dec
end
OUT["输出 tokens"]:::io
IN --> ENC
ENC -->|"H_20 隐藏态"| PROJ
PROJ --> DEC
DEC --> OUT
图 1 · 模型架构(源自《Flash 推理加速解读》):20 层编码器 + 20 层解码器,两段之间 KV 投影连接
四步递进的推理配置 (该篇的主线,也是「改了啥」的完整答案):
① baseline :每层自算自存,40 份 KV——固有瓶颈本体;
② Prefill / Decode 分离 :Prefill 拿完整输入一次算完,产出两样——对输入的完整理解 H_20 与解码器要用的全局 KV(此阶段解码器 20 层完全不执行);Decode 每步只处理单个新 token,解码器基于投影的全局 KV 做注意力逐步生成;
③ CED :Prefill 只跑编码器,解码器的 KV 缓存不再由自己计算,而是直接从编码器输出投影得到——计算量减半 ;
④ CSA2 :解码段分共享组,每组一个 Full 层(主 KV + 索引器 K + Top-K)带若干 Reindex(复用 KV、重选 Top-K)与 Reuse(KV 与 Top-K 全复用)层——存储量大幅下降 。
flowchart TD
classDef enc fill:#ddf4ff,stroke:#0969da,color:#0969da,stroke-width:1.5px
classDef dec fill:#fbefff,stroke:#8250df,color:#8250df,stroke-width:1.5px
classDef bad fill:#ffebe9,stroke:#cf222e,color:#cf222e,stroke-width:1.5px
classDef good fill:#dafbe1,stroke:#1a7f37,color:#1a7f37,stroke-width:1.5px
classDef io fill:#f6f8fa,stroke:#8b949e,color:#1f2328,stroke-width:1.5px
subgraph OLD["无 CED · Prefill 跑满 40 层"]
direction LR
A1["输入 30K tokens"]:::io --> B1["编码器 20 层"]:::enc
B1 --> C1["解码器 20 层自己算 KV "]:::dec
C1 --> D1["Prefill 激活480,000 B "]:::bad
end
subgraph NEW["有 CED · Prefill 只跑 20 层"]
direction LR
A2["输入 30K tokens"]:::io --> B2["编码器 20 层"]:::enc
B2 -->|"KV 投影"| C2["解码器 20 层不重算 KV "]:::dec
C2 --> D2["Prefill 激活240,000 B "]:::good
end
图 2 · CED 机制(源自《Flash 推理加速解读》):无 CED 时 Prefill 跑满 40 层;CED 只跑编码器,解码段 KV 由 H_20 投影,计算量减半
flowchart LR
classDef full fill:#0969da,stroke:#0969da,color:#ffffff,stroke-width:1.5px
classDef reindex fill:#54aeff,stroke:#0969da,color:#1f2328,stroke-width:1.2px
classDef reuse fill:#cae8ff,stroke:#0969da,color:#1f2328,stroke-width:1.2px
classDef src fill:#ddf4ff,stroke:#0969da,color:#0969da,stroke-width:1.5px
ENC["编码器 · 层 1–20 正常逐层前向"]:::src --> H20["H_20 · 编码器末层隐藏态 解码段 层 21–40 全局 KV 的唯一来源"]:::src
H20 -->|"KV 投影 W₂₁"| FA
H20 -->|"KV 投影 W₂₅"| FB
H20 -->|"KV 投影 W₂₉"| FC
H20 -->|"KV 投影 W₃₃"| FD
H20 -->|"KV 投影 W₃₇"| FE
subgraph GA["共享组 1 · 层 21–24"]
direction LR
FA["层 21 · Full 投影 W₂₁(H_20) 持有 主 KV + 索引器 K + Top-K"]:::full
RA["层 22 · Reuse KV 与 Top-K 全复用"]:::reuse
RB["层 23 · Reindex 复用 KV,重选 Top-K"]:::reindex
RC["层 24 · Reuse KV 与 Top-K 全复用"]:::reuse
FA -.->|共享| RA
FA -.->|共享| RB
FA -.->|共享| RC
end
subgraph GB["共享组 2 · 层 25–28"]
direction LR
FB["层 25 · Full 投影 W₂₅(H_20) 持有 主 KV + 索引器 K + Top-K"]:::full
RD["层 26 · Reuse KV 与 Top-K 全复用"]:::reuse
RE["层 27 · Reindex 复用 KV,重选 Top-K"]:::reindex
RF["层 28 · Reuse KV 与 Top-K 全复用"]:::reuse
FB -.->|共享| RD
FB -.->|共享| RE
FB -.->|共享| RF
end
subgraph GC["共享组 3 · 层 29–32"]
direction LR
FC["层 29 · Full 投影 W₂₉(H_20) 持有 主 KV + 索引器 K + Top-K"]:::full
RG["层 30 · Reuse KV 与 Top-K 全复用"]:::reuse
RH["层 31 · Reindex 复用 KV,重选 Top-K"]:::reindex
RI["层 32 · Reuse KV 与 Top-K 全复用"]:::reuse
FC -.->|共享| RG
FC -.->|共享| RH
FC -.->|共享| RI
end
subgraph GD["共享组 4 · 层 33–36"]
direction LR
FD["层 33 · Full 投影 W₃₃(H_20) 持有 主 KV + 索引器 K + Top-K"]:::full
RJ["层 34 · Reuse KV 与 Top-K 全复用"]:::reuse
RK["层 35 · Reindex 复用 KV,重选 Top-K"]:::reindex
RL["层 36 · Reuse KV 与 Top-K 全复用"]:::reuse
FD -.->|共享| RJ
FD -.->|共享| RK
FD -.->|共享| RL
end
subgraph GE["共享组 5 · 层 37–40"]
direction LR
FE["层 37 · Full 投影 W₃₇(H_20) 持有 主 KV + 索引器 K + Top-K"]:::full
RM["层 38 · Reuse KV 与 Top-K 全复用"]:::reuse
RN["层 39 · Reindex 复用 KV,重选 Top-K"]:::reindex
RO["层 40 · Reuse KV 与 Top-K 全复用"]:::reuse
FE -.->|共享| RM
FE -.->|共享| RN
FE -.->|共享| RO
end
图 3 · CSA2 机制(源自《Flash 推理加速解读》):H_20 经各层投影生成层 21–40 的主 KV(5 组各一个 Full 层持有),组内 Reindex / Reuse 复用 KV 与 Top-K
量化效果四笔账 :
账目 数字 口径说明
CSA2 收益 KV 存储容量压缩至基线 1/4 全注意力层共享同一份 KV + 小型转换模块跨层映射
CED + CSA2 叠加 持久化 Prefix 缓存约 1/8 同一条请求的落盘口径
全局 KV 890 B/token 2.5 条/token ×(288 B 主记录 + 68 B 索引);V4.0 同口径约 3,514 B/token
长上下文实例 31,000 token × 890 B = 27.6 MB,↓75% 该篇同源数字(持久化缓存/SSD 口径)
FP4 的位置 :主 KV 从 FP8 下到 FP4(E2M1,每 16 通道一个 E4M3 scale,无 per-tensor scale)——这是在 CED 和 CSA2 已减过份数之后的动作,不是全局一刀切:SWA KV 仍保留 FP8 。主记录 512 值 × FP4 = 256 B 加 32 B scale;索引 128 值 × FP4 = 64 B 加 4 B scale。省掉二级全局 scale 的数值前提:E2M1 只有 1 位尾数,实际 KV 最大幅度约 10,scale 上界约 2048,余量近两个数量级。
# FP4 E2M1 主 KV 量化,per-16-channel E4M3 scale
def quantize_fp4_e2m1(x): # x: [..., 512]
x = x.view(..., 512 // 16, 16) # 每 16 通道一组
scale = x.abs().amax(dim=-1) / 6.0 # 6 = E2M1 最大幅值
scale = scale.clamp(min_e4m3, max_e4m3) # 无 per-tensor scale
q = (x / scale.unsqueeze(-1)).round() # 4 bit 量化
return q, scale # 256 B + 32 B = 288 B
2. KV Cache 演进:MLA → V4.0 三段分段 → V4.1 换路径
台阶总览 :MLA 基准 70,272 B/token → V4.0 约 3,514 B/token → V4.1 约 890 B/token。三个阶段压的是不同的东西:MLA 压每层存什么;V4.0 压序列维度(按时长分段);V4.1 压份数(换生成路径 + 层间复用) 。
基准 MLA :特征维低秩——不为每个 head 存完整 K/V,存 512 维 latent 加 64 维 RoPE key,每 token 每层 576 标量;61 层线性累加到 70,272 B/token。层与层之间没有连线:各自生成、各自持有,「每层各存一份」这个乘数没动 。
flowchart LR
subgraph L1["层号(竖排)"]
direction TB
A1["Layer 1 h_t → Q/K/V → W_DKV 下投影"]
A2["Layer 2 h_t → Q/K/V → W_DKV 下投影"]
A3["Layer 3 h_t → Q/K/V → W_DKV 下投影"]
AD["..."]
A61["Layer 61 h_t → Q/K/V → W_DKV 下投影"]
end
A1 --> P1["latent 512 + RoPE 64 = 576 标量 × 2 B = 1,152 B/token"]
A2 --> P2["1,152 B/token"]
A3 --> P3["1,152 B/token"]
AD --> PD["..."]
A61 --> P61["1,152 B/token"]
P1 --> SUM["全局 KV = 61 × 1,152 B = 70,272 B/token"]
P61 --> SUM
图 4 · MLA 基准:每层独立低秩,61 × 1,152 B = 70,272 B/token——压的是每层存什么,份数乘数未动
V4.0 的三段分段 :在特征维度之外沿序列维度加压,且按上下文长度分段:
上下文区间 注意力类型 压缩比 重叠 角色
0–4K Full-Attn 不压缩 — 近处保留原始 KV,保证短距精度
4K–100K CSA 4:1 有,4 token 近中程稀疏检索,带 Indexer
超过 100K HCA 128:1 无 远程极粗压缩,省容量,无 Indexer
CSA 段 :步长 4、窗口 8、重叠 4,块间保留一半重叠——这个重叠是它在边界处不崩的原因。21 层 CSA 主 KV 合计约 3,066 B/token,是 V4.0 全局 KV 的大头。
flowchart LR
subgraph L2["CSA 层号(竖排)"]
direction TB
B2["Layer 2 h_t → Q/K/V → 4:1 压缩 + Indexer"]
B3["Layer 3 h_t → Q/K/V → 4:1 压缩 + Indexer"]
B4["Layer 4 h_t → Q/K/V → 4:1 压缩 + Indexer"]
BD1["..."]
B22["Layer 22 h_t → Q/K/V → 4:1 压缩 + Indexer"]
end
B2 --> C2["Q 查 Top-K 压缩块 K/V 压成 4:1 entry 步长 4,窗口 8,重叠 4 146 B/token"]
B3 --> C3["146 B/token"]
B4 --> C4["146 B/token"]
BD1 --> CD1["..."]
B22 --> C22["146 B/token"]
C2 --> CHUNK["切块:token 0-7 窗口 8 token 4-11 窗口 8,重叠 4 token 8-15 窗口 8,重叠 4"]
C3 --> CHUNK
C4 --> CHUNK
CD1 --> CHUNK
C22 --> CHUNK
CHUNK --> SUM2["21 层 CSA 21 × 146 ≈ 3,066 B/token"]
图 5 · V4.0 CSA:21 层 × 146 B ≈ 3,066 B/token,4:1 带重叠 + Indexer Top-K
HCA 段 :每 128 个 token 压成一条 entry,块间首尾相接、没有重叠;每层 query 直接看全部压缩块(无 Indexer)。20 层 HCA 合计仅约 91 B/token——省,但把风险集中在边界上(第 3 章展开)。
flowchart LR
subgraph RAW["原始 token(最左列)"]
direction TB
R1["token 0–127"]
R2["token 128–255"]
R3["..."]
R4["token 3968–4095"]
end
R1 -->|"128:1"| K1["压缩块 A 1 条 entry"]
R2 -->|"128:1"| K2["压缩块 B 1 条 entry"]
R3 -->|"128:1"| KD["..."]
R4 -->|"128:1"| K4["压缩块 32 1 条 entry"]
subgraph L3["HCA 层号(竖排)"]
direction TB
D23["Layer 23 h_t → Q/K/V Q 看全部压缩块"]
D24["Layer 24 h_t → Q/K/V Q 看全部压缩块"]
D25["Layer 25 h_t → Q/K/V Q 看全部压缩块"]
DD2["..."]
D42["Layer 42 h_t → Q/K/V Q 看全部压缩块"]
end
K1 --> D23
K2 --> D23
KD --> D23
K4 --> D23
D23 --> H23["无重叠,无 Indexer 4.56 B/token/层"]
D24 --> H24["4.56 B/token/层"]
D25 --> H25["4.56 B/token/层"]
DD2 --> HD2["..."]
D42 --> H42["4.56 B/token/层"]
H23 --> BOUNDARY["边界问题 query 在 127/128 边界 证据被切到相邻块 最坏检索 -40%"]
H24 --> BOUNDARY
H25 --> BOUNDARY
HD2 --> BOUNDARY
H42 --> BOUNDARY
BOUNDARY --> SUM3["20 层 HCA 20 × 4.56 ≈ 91 B/token V4.0 总全局 ≈ 3,514 B/token"]
图 6 · V4.0 HCA:128:1 无重叠,20 × 4.56 ≈ 91 B/token;V4.0 全局合计约 3,514 B/token
V4.1 的两件事 :一是 CED 拆分 ——后 20 层的全局 KV 从 H_20 投影分发,不再逐层自产,全局 KV 生成维度上 40 层工作量接近减半;二是 CSA2 层间复用 ——Full 层完整生成主 KV 和 indexer K,Reindex 层共享主 KV 只重算 Top-K,Reuse 层连索引也复用,真正独立持有全局 KV 的只剩少数源层。压缩比从 4 降到 2(步长 2、窗口 4、重叠 2)。
flowchart LR
subgraph LAYERS["层号(竖排)"]
direction TB
E1["Layer 1 h_t → Q/K/V → CSA2 2:1 编码"]
E2["Layer 2 h_t → Q/K/V → CSA2 2:1 编码"]
E3["Layer 3 h_t → Q/K/V → CSA2 2:1 编码"]
ED["..."]
E20["Layer 20 h_t → Q/K/V → CSA2 2:1 编码"]
D21["Layer 21 从 H_20 投影得 KV → CSA2 Full"]
D22["Layer 22 从 H_20 投影得 KV → CSA2 Reindex"]
D23["Layer 23 从 H_20 投影得 KV → CSA2 Reuse"]
DD["..."]
D40["Layer 40 从 H_20 投影得 KV → CSA2 Reuse"]
end
subgraph ENC["前 20 层:Causal Encoder"]
direction TB
EN1["逐层编码"] --> EN2["汇总全部上下文"]
EN2 --> H20["H_20 Encoder 最终隐藏状态 一份浓缩摘要"]
end
E1 --> EN1
E2 --> EN1
E3 --> EN1
ED --> EN1
E20 --> EN1
subgraph PROJ["投影分发(一次 matmul,无 attention)"]
direction TB
P["每层独立投影权重 W 从 H_20 取出该层全局 KV"]
end
H20 --> P
subgraph DEC["后 20 层:Decoder(CSA2)"]
direction TB
DF["Full 层 持有主 KV + indexer K"]
DR["Reindex 层 共享主 KV,重算 Top-K"]
DU["Reuse 层 直接复用,不新增"]
end
P --> DF
P --> DR
P --> DU
D21 -.-> DF
D22 -.-> DR
D23 -.-> DU
DD -.-> DU
D40 -.-> DU
DF --> SUM4["全局 KV = 890 B/token 2.5 条/token × (288 + 68) B"]
DR --> SUM4
DU --> SUM4
图 7 · V4.1 CED + CSA2:H_20 投影分发(一次 matmul)+ Full/Reindex/Reuse 复用 → 全局 890 B/token
3. HCA 为什么退场:无重叠的相位代价
根因一条 :128:1 压缩且块间无重叠 ——query 落在 127/128 这类边界时,需要的证据被切到相邻块。字节 Seed 实测里,V4-Flash 在 128K 检索任务中最好与最差位置组的准确率差约 40 个百分点 ,波动周期与分块步长一致。站内《固定窗口压缩的相位敏感性》一篇专门展开了这个现象。
flowchart LR
subgraph L5["Decoder 层号(竖排,原 HCA 位置)"]
direction TB
G23["Layer 23 从 H_20 投影得 KV h_t → Q/K/V"]
G24["Layer 24 从 H_20 投影得 KV h_t → Q/K/V"]
G25["Layer 25 从 H_20 投影得 KV h_t → Q/K/V"]
GD2["..."]
G40["Layer 40 从 H_20 投影得 KV h_t → Q/K/V"]
end
G23 --> COMPARE["同一段层,两代处理方式"]
G24 --> COMPARE
G25 --> COMPARE
GD2 --> COMPARE
G40 --> COMPARE
COMPARE --> OLD["V4.0 这段:HCA 128:1 每层自己从 h_t 生成 KV 无重叠,无 Indexer 4.56 B/token/层 边界最坏 -40%"]
COMPARE --> NEW["V4.1 这段:从 H_20 投影得 KV K/V → CSA2 2:1 带重叠 带 Indexer,Q 查 Top-K 100K 门限作废 4K–1M 全 CSA2"]
OLD --> RESULT["最坏相位劣化 40% → 约 6% 没有清零"]
NEW --> RESULT
图 8 · 同一段层的两代处理:HCA 128:1 无重叠 → CSA2 2:1 带重叠带 Indexer,最坏相位劣化约 40% → 约 6%
三条边界要交代 :
相位问题没有消除 :CSA2 步长从 4 降到 2,最坏劣化从约 40 个百分点压到约 6%,周期性波动仍在,只是幅度可控;
删 HCA ≠ 更省显存 :HCA 是无重叠极端压缩,取消后同等 1M 上下文的 KV 条目数比开 HCA 的 V4-Flash 更多,V4.1 靠 FP4 把整体显存压回来;
V4-Pro 不受影响 :它仍是 CSA + HCA 混合架构,4K/100K 阈值继续生效——讲「V4.1 删了 HCA」要限定到 Flash 支线。
4. 训练说明:老师-学生结构与三段关键代码
训练结构(参考图) :老师是 SWA(滑动窗口 128,冻结 ❄),学生在 SWA 之外多出一条可学习的 KV 分支 (θ 标记为可训练参数)——HCA 版把历史压成 128:1 无重叠的压缩条目 + 滑窗原始 KV 做 Shared-KV MQA;CSA 版用 4:1 重叠压缩 + Lightning Indexer 打分选 Top-K,Indexer 因 Top-K 掩码不可导而加辅助损失 L_idx。
输入 Hidden States H
👨🏫 老师 · SWA(滑动窗口 · 冻结 ❄)
输入 H
LayerNorm
Q 投影
K 投影
V 投影
滑窗 MQA
仅最近 128 token
仅最近 128 token
O 投影 ⊕ 残差
FFN (SwiGLU)
⊕ 残差
输出 H′
🧑🎓 学生 · SWA + HCA(KV 学习分支为重点)
输入 H
LayerNorm
KV 学习分支(HCA · 可学习)
压缩权重
Z = H·W^Z
θ: W^Z·B
KV 投影
C = H·W^KV
θ: W^KV
S = Softmax(Z_block + B)
C^Comp = Σ S_j ⊙ C_j
128:1 无重叠 · 仅本块
最近滑窗原始 KV
(取最近窗口 · 经 W^KV)
低秩 Q 投影 θ: W^DQ·W^UQ
c^Q = h·W^DQ → q =
c^Q·W^UQ
Shared-KV MQA
K = V = 压缩条目 + 滑窗原始 KV
K = V = 压缩条目 + 滑窗原始 KV
O 投影 ⊕ 残差
θ: W_O
θ: W_O
FFN (SwiGLU)
⊕ 残差
输出 H′
Loss 计算
(LM 损失 + 蒸馏对齐)
压缩 KV(K=V)
原始 KV(局部兜底)
教师输出 · 软标签
学生输出 · 预测
梯度回传(仅学生 θ)
更新 W^DQ、W^UQ
更新 W^Z、B
更新 W^KV
红色虚线 = 梯度回传(仅学生侧参数 θ 被更新)
灰色节点 = 老师(SWA,❄ 冻结,无梯度)
黄色虚线框 = KV 学习分支(本图重点:公式与参数齐全;图 2 无 Indexer,全程可导)
图 9 · 训练结构·学生 SWA + HCA 分支:压缩权重 Z=H·W^Z 经 Softmax 聚合,128:1 无重叠 + 滑窗原始 KV,低秩 Q 投影
输入 Hidden States H
👨🏫 老师 · SWA(滑动窗口 · 冻结 ❄)
输入 H
LayerNorm
Q 投影
K 投影
V 投影
滑窗 MQA
仅最近 128 token
仅最近 128 token
O 投影 ⊕ 残差
FFN (SwiGLU)
⊕ 残差
输出 H′
🧑🎓 学生 · SWA + CSA(KV 学习分支为重点)
输入 H
LayerNorm
KV 学习分支(CSA · 可学习)
压缩权重
Z = H·W^Z
θ: W^Z·B
KV 投影
C = H·W^KV
θ: W^KV
S = Softmax(Z_block + B)
C^Comp = Σ S_j ⊙ C_j
4:1 重叠 · 当前块+前一块
Lightning Indexer
打分选 Top-K · θ: W_idx
打分选 Top-K · θ: W_idx
Indexer 辅助损失 L_idx
(Top-K 掩码不可导)
Q 投影
θ: W_Q
θ: W_Q
稀疏 MQA
仅 Top-K 块 · K = V = 压缩条目
仅 Top-K 块 · K = V = 压缩条目
O 投影 ⊕ 残差
θ: W_O
θ: W_O
FFN (SwiGLU)
⊕ 残差
输出 H′
Loss 计算
(LM 损失 + 蒸馏对齐)
压缩条目
索引分数
压缩 KV(K=V)
Top-K 掩码
教师输出 · 软标签
学生输出 · 预测
梯度回传(仅学生 θ)
更新 W_Q
更新 W^Z、B
更新 W^KV
更新 W_idx
红色虚线 = 梯度回传(仅学生侧参数 θ 被更新)
灰色节点 = 老师(SWA,❄ 冻结,无梯度)
黄色虚线框 = KV 学习分支(本图重点:公式与参数齐全)
橙色节点 = Indexer 辅助损失(Top-K 掩码不可导,仅图 1 有)
图 10 · 训练结构·学生 SWA + CSA 分支:4:1 重叠(当前块+前一块)+ Lightning Indexer 选 Top-K + 辅助损失 L_idx
复现侧的三段核心代码 (完整版见复现实测.md):CED 主投影器 Linear(2560, 2048) 约 5.24M 参数,输出前 1024 维作 K、后 1024 维作 V:
class CEDProjector(nn.Module):
"""Linear(hidden -> 2*KV_DIM),输出前 1024 为 K、后 1024 为 V"""
def __init__(self, input_dim=config.PROJ_INPUT_DIM, output_dim=config.PROJ_OUTPUT_DIM):
super().__init__()
self.proj = nn.Linear(input_dim, output_dim, bias=True)
def forward(self, h16: torch.Tensor):
out = self.proj(h16)
return out[..., : out.shape[-1] // 2], out[..., out.shape[-1] // 2 :]
CSA2 适配器 :闭式解线性基座 + 残差修正。这里踩过一个坑——ResidualMLP 若前后两层都零初始化,梯度恒为零,残差分支成死区 ;改成只零初始化最后一层、前层随机初始化后,V 的 R² 从 0.57~0.69 提升到 0.67~0.83:
class ResidualMLPAdapter(nn.Module):
"""闭式解线性基座 + 残差修正:y = base(x) + refine(x)。
refine 末层零初始化(起点等价闭式解);前层保持默认随机初始化——
若两层全零,W1/W2 梯度恒为零,残差分支成死区(已踩坑,勿改回)。"""
def __init__(self, dim, hidden=None):
super().__init__()
hidden = hidden or dim * 2
self.base = nn.Linear(dim, dim)
self.refine = nn.Sequential(
nn.Linear(dim, hidden), nn.GELU(), nn.Linear(hidden, dim)
)
nn.init.zeros_(self.refine[2].weight)
nn.init.zeros_(self.refine[2].bias)
def forward(self, x):
return self.base(x) + self.refine(x)
岭回归闭式解初始化 :让适配器起点等价于「最优线性映射」,SGD 只补非线性残差:
@torch.no_grad()
def init_from_closed_form(self, x_k, y_k, x_v, y_v, lam=1.0):
"""闭式解(岭回归)初始化:x (N,dim) -> y (N,dim)。
Linear:直接求解;ResidualMLP:初始化 base 分支(refine 保持零)。"""
for map_module, x, y in ((self.k_map, x_k, y_k), (self.v_map, x_v, y_v)):
target = map_module if isinstance(map_module, nn.Linear) else map_module.base
xa = torch.cat([x, torch.ones(x.shape[0], 1, device=x.device)], dim=1)
w = torch.linalg.solve(xa.T @ xa + lam * torch.eye(xa.shape[1], device=x.device), xa.T @ y)
target.weight.copy_(w[:-1].T)
target.bias.copy_(w[-1])
5. 复现实测:设定、结果与边界
设定 :Qwen3.5-4B 冻结主干,hook 一次 forward 捕获第 16 层隐藏态 H_16 与第 20/24/28/32 层的 k_proj/v_proj 输出(pre-norm、pre-RoPE 空间),1200 条样本落盘 12.2GB;CED 投影器 MSE 收敛 0.0658。与官方的关键差异:官方是从头预训练时协同学习 投影器与适配器,复现是在已收敛表示空间里做映射拟合 ——验证的是机制可行性,不是原始训练配方。
flowchart TD
A[输入 tokens] --> B["layers 0..15 编码段"]
B --> C["H_16 第16层隐藏态 (L, 2560)"]
C --> D["P(H_16) Linear 2560→2048"]
D --> E["K_20, V_20 (L, 1024) × 2"]
C --> F["layers 16..31 解码段"]
E --> F
F --> G[输出 logits]
图 11 · CED 在 32 层里的位置:第 16 层切分,H_16 经 Linear 2560→2048 投影出解码段全注意力层的 KV
flowchart TD
A["第20层 Full 模式 K_20, V_20"] --> B["K_20, V_20 1 份存储"]
B --> C["第24层适配器 K: Linear V: ResidualMLP"]
B --> D["第28层适配器 K: Linear V: ResidualMLP"]
B --> E["第32层适配器 K: Linear V: ResidualMLP"]
C --> F["K_24, V_24"]
D --> G["K_28, V_28"]
E --> H["K_32, V_32"]
图 12 · CSA2 共享机制:只保留第 20 层 1 份 KV,第 24/28/32 层各挂小适配器做跨层映射(每层约 1M 参数)
flowchart TD
A["输入 tokens"] --> B["编码段 layers 0..15"]
B --> C["H_16"]
C --> D["CED 投影器 P Linear 2560→2048"]
D --> E["K_20, V_20 全量 KV"]
E --> F["CSA2 适配器 × 3 → K_24/V_24, K_28/V_28, K_32/V_32"]
F --> G["TurboQuant k8v4 K 8bit / V 4bit"]
G --> H["解码段 attention layers 16..31"]
H --> I["输出 logits"]
图 13 · 三者叠加的数据流:CED 投影 → CSA2 共享 → TurboQuant k8v4 量化 → 解码段 attention
四项主要结果 :
指标 baseline CED + CSA2 / 量化 判定
GSM8K(100 题) 0.760 0.750(-1pp) 基本无损
NIAH(50 条,8K 上下文) 0.940 0.920(-2pp) 基本无损
Prefill 延迟 @2048 / 1024 / 512 589.9 ms 387.9 ms;1.56x / 1.27x / 1.18x 加速成立,随长度增长
KV 解码段压缩(持久口径) 1x 3.44x(L 大时趋近 4x) 达标
KV 全模型压缩(持久口径) 1x 1.60x(=理论 8/5) 达标
k8v4 量化压缩比 1x 2.46x(理论 2.53x) 达标
k8v4 top-5 重合 / top-1 一致 — 100% / 88.9% 轻微扰动
两个必须说清的口径(易误读)
持久 ≠ 驻留 :3.44x 是落盘/最小集合口径;运行时 reuse 层的物化视图仍占 HBM,驻留口径约 1.00x——当前实现是「落盘压缩 + 计算复用」,不是显存压缩,显存 4x 需要 attention 内惰性物化(后续工作)。mode_b 有适用边界 :解码段含 24 层 GatedDeltaNet(递归结构),从零状态起步无法携带历史——mode_b 适合 prefill 延迟优化与 next-token 评测,连续生成要走 mode_csa2_adapter;只旁路 4 个全注意力层时加速从 1.52x 回落 1.10x,这是架构约束不是实现 bug。
可信度交叉验证 :手动逐层 decode 与官方 forward 的 max|Δlogit| = 0.0000、top-1 完全一致;固定位置 H_16 在总长 32~256 下 fp32 零差异(因果性严格);分块 kernel 对末尾不完整 chunk 的 ~2^-5 量级差异与后缀内容无关,确认为非因果泄漏。关键前提一条 :跨层 KV 不能直接复用——第 20 层与第 24/28/32 层 KV 余弦相似度约 0,必须经可训练适配器映射,映射后 R² 到 0.67~0.85。
6. 结论与来源
结论三句 :演进主线索是「压每份 → 压序列 → 压份数」,V4.1 用 CED+CSA2 换掉逐层自产,用带重叠的 CSA2 接住 HCA 退场后的远程段,FP4 收位宽,全局 890 B/token、持久化 1/8;相位问题从 40pp 压到约 6pp 但未消除;复现侧在 4B 混合架构上验证机制成立——生成质量基本无损、prefill 加速与持久压缩达标、量化扰动轻微,规模与架构差异是结论的边界。
来源与互链 :第 1 章与图 1–3 取自站内《DeepSeek-V4.1-Flash 推理加速解读 》 (四步递进的推理配置与量化效果);HCA 相位现象的专门展开见《DeepSeek-V4.1 固定窗口压缩的相位敏感性 》 ;第 2、3 章基于 KV 演进底稿(图 4–8),第 4、5 章基于 CED+CSA2 复现实测记录(图 9–13 与四段代码);训练结构参考图为老师-学生 SWA 结构两式(HCA / CSA)。
汇总篇 · 2026-10-19 发布 · 第 1 章图 1–3 取自《Flash 推理加速解读》,相位现象详见《固定窗口压缩的相位敏感性》;数字与结论均取自所引素材