DeepSeek-V4.1-Flash 架构解析:KV Cache 压缩的极限在哪里
DeepSeek-V4.1-Flash 的技术报告副标题是 “Pushing the Limits of KV Cache Compression”——整篇论文的野心写在脸上:把 KV Cache 压到极致,把长上下文 Agent 负载的部署成本打下来。552B 骨干 + 196B 条件记忆,prefill 每 token 只激活 8B 参数,全局 KV 压到 890 字节/token(约 V4-Flash 的 1/4、V1 的 1/437),持久化 KV 压到 V4-Flash 的约 1/8。本文按报告第 2 章(架构)和第 3 章(推理系统)的顺序,把六个核心设计串成一条线:CED、CSA2、SWA Bounded Replay、Single-Pass mHC、FP4 主 KV、DSpark 与 Engram,最后算一笔总账。数字口径除标注外均来自论文原文,部分以 vLLM 实现/HF config 佐证。
1. 全景:一张表和一个劈半动作
| 项 | 数值 |
|---|---|
| 骨干参数 | 552B(MoE,1 共享 + 384 路由专家,激活 6 个,专家中间维 2304) |
| Engram 条件记忆参数 | 196B(单独计,不计入骨干) |
| 激活参数 | prefill 每token 8B / decode 每token 16B |
| 层数与结构 | 40 层 = 20 层因果编码器 + 20 层解码器(CED) |
| 隐维度 | 5120,64 查询头 × 头维 512;q_lora 1280,输出侧 8 组 × o_lora 1024 |
| 上下文长度 | 100 万 token(64K 起步稀疏注意力训练,34T token 处扩到 1M) |
| 预训练语料 | 45T token(文本:多模态 = 7:1) |
一句话概括架构:把一个标准 Transformer 从中间劈开——前 20 层当"因果编码器"处理全部输入,后 20 层当"解码器",其全局 KV 不再自己算,而是从编码器最后一层的隐状态投影出来;再叠加跨层 KV 共享、FP4 缓存与滑窗,完成上面那组压缩数字。
2. CED:编码器算一半,解码器借结果
Agent 工作流中频繁的工具调用产生大量 prefill 请求,KV 未命中时 prefill 计算是主要开销。CED(受 YoCo 启发)的目标是砍掉一半 prefill 计算:对全局注意力,解码器各层()的 KV 条目不来自本层隐状态 ,而是由编码器最后一层隐状态经逐层独立投影直接算出:
C 是 KV 条目,Z 是对应压缩权重。投影是一次线性变换,相比"一整层 Transformer(注意力+FFN)"开销可忽略,后半层几乎免费拿到全局 KV。序列长度 时 prefill 复杂度从 降到约 ——这就是 prefill 激活 8B、decode 激活 16B 的来源。
两点澄清:每个解码层的注意力照常进行、KV 有得读,变的只是计算来源;部署配置下上式进一步塌缩——实际只有解码器第一个 Full 层(层 20)执行投影并落缓存,层 21–39 直接读这一份(HF config 佐证:kv_source_layer_ids = [2, 8, 14, 20],且这次投影与该层 Q 投影融合成单个 GEMM,vLLM 的 fused_wqa_wkv)。
SWA 维持逐层常规计算,保住局部特征的计算深度;代价是解码器 SWA 需要重放过程,见第 4 节。
3. CSA2:三个维度同时压缩
3.1 三个乘性维度
长上下文的 KV 开销可以沿三个维度相乘式压缩:条目大小(GQA 减 KV 头、MLA 共享 latent)、序列维度(每 m 个 token 压成 1 条)、层维度(部分层复用其他层的缓存/索引)。既有工作各占一维,CSA2 三个同时吃满。相对 V4 的 CSA:压缩比 m 的每条主 KV 不再去掉重叠与绝对位置编码;indexer K 不再从隐状态单独压缩,而是直接由主 KV 条目投影——少一条管线,且索引器与注意力读到逐位对应的内容。
3.2 三种静态模式与部署配置
每层静态指定 Full / Reindex / Reuse 三种模式之一,区别只在于 main KV、indexer K、Top-K 索引从哪来:
| 模式 | main KV + indexer K | Top-K 索引 | 开销 |
|---|---|---|---|
| Full | 本层自己算 | 全量打分,产出新索引 | 最重 |
| Reindex | 复用最近 Full 层 | 自己的 indexer Q 对共享 K 重新打分 | 中 |
| Reuse | 复用最近 Full 层 | 复用最近产索引层的索引 | 最轻 |
部署配置(HF config 佐证):层 0–1 纯 SWA(m=0);编码器层 2–19 压缩比 m=2(3 组 × 6 层,Full 在 2/8/14,其余全 Reuse);解码器层 20–39 m=1(5 组 × 4 层:首组 1 Full + 3 Reuse,其余 4 组各 1 Reindex + 3 Reuse)。m=1 的含义值得咀嚼:解码器放弃序列维度压缩、保留逐 token 粒度,把压缩收益改从层维度共享(全解码器只有 1 份全局 KV)与 FP4 精度里拿——这是 V4.1 相对 V4(C4/C128)最大的思路转变。
m=0 的常见疑问:头两层只看 SWA 窗口 128,长上下文是不是"彻底没了"?不是——上下文不靠每层各自看见,而靠分工:层 0–1 把每个 token 加工为局部特征写入残差流,特征向上进入 H₂₀ 被压缩为全局缓存条目,远距离 query 在高层 CSA2 里按需检索。即"低层局部加工 → 残差流运输 → 高层全局检索"。
Z(压缩权重)的计算:kv-source 层对每 token 隐状态做两个并行投影——wkv 产出 512 维 latent,wgate 产出 512 维门控分数;按 m 分组后组内做逐通道 softmax 加权求和(每个通道有自己的组内混合权重,不是标量门)。池化后 RMSNorm → 无 RoPE 版本 → 压缩 RoPE(theta=160000)→ FP4 量化入缓存。m=1 时整条门控路径不存在——解码器层 20 的缓存条目就是 wkv 投影 + RMSNorm,论文式(1)的 Z 是 m>1 的一般形式。
3.3 分层稀疏索引器:16384 → 2048 → 512 的漏斗
超长上下文下索引器给全上下文打分是 decode 的主要计算瓶颈。分层索引器用四级漏斗解决(仅解码器):
- 建池——唯一一次全量过滤:解码器第一个 Full 层(层 20)对全部可见位置打分,为自己的注意力选出 Top-512;同一份分数顺手完成块级候选选择——位置按 8 个一组分块,每块取块内最大索引分(块 max 是上界,强相关块不会被漏),选出最高的至多 2048 块,展开为至多 2048×8 = 16384 个候选位置,构成共享候选池
- 池内过滤——4 次,常数开销:4 个 Reindex 层(24/28/32/36)用自己的 indexer Q 只对池内候选重新打分,各自选出 Top-512——深层索引器的每查询开销从"正比于上下文长度"变为常数
- 纯继承——15 个 Reuse 层:不做任何打分。每个 decode step 的索引账 = 1 次全量打分 + 4 次池内打分 + 15 次继承
- 旁路与边界:滑窗最近 token 不经漏斗,展开池块后直接并入尾部,最新上下文不因块未攒满而丢失
时序澄清(容易读错):top-2048 与 top-512 是同一次打分、同一处的两次并行 Top-K(位置级取 512 自用、块级取 2048 展开建池),不是"先选 512 再基于 512 建池"。每个 decode step 各走一遍。该机制在 post-training 引入且训练/推理一致——deeper indexer 在与推理相同的搜索域上被优化。
4. SWA Bounded Replay:按生命周期分治
4.1 为什么 SWA 不值得持久化
每层 SWA 窗口 128,SWA KV 以 FP8 存储(对量化敏感,不随主 KV 降 FP4)。V4 部署中 SWA KV 约占持久缓存容量一半,但只在两个点缓存(prompt 末尾、output 末尾各留 128 条),复用只发生在分钟级会话窗口内,会话结束即死——与持久缓存 72 小时的长留存策略根本不匹配:贵且低效。
4.2 精确重建为什么是 5120——"楼梯"式感受野
V4 曾提出 Zero SWA Caching(缺了就精确重算),但精确恢复需要 L×n_win = 40×128 = 5120 token 的完整前向。SWA 的 K/V 本身便宜,贵在隐状态的跨层依赖:第 l 层位置 i 的值由第 l−1 层窗口 [i−127, i] 构成——每往深一层,所需历史的左边界再扩一个窗口,形成楼梯:
| 层 | 精确重建所需历史 |
|---|---|
| 40(目标) | [p−127, p] |
| 39 | [p−254, p] |
| ⋮ | 每降一层再扩一个窗口 |
| 1(底座) | [p−5119, p] ≈ 40×128 |
正常 prefill 不付这笔账(楼梯被逐位置计算摊销),只有断点冷启动重建时才显形。
4.3 Bounded Replay:只重放 128 个
重放只取前缀最后 n_win=128 个 token 过全部 L 层,补出各层 SWA 缓存的最后 128 个槽位;重放期间滑窗左边界截断到重放起点。近似性:重放段靠前的 token 历史被砍短(越靠后越精确,最后一个 token 精确);重放过程中新算的全局 KV 直接丢弃不覆盖缓存。代价从 5120 骤降到 128,且与上下文长度无关。
三种方案成本对照(10,000 token 前缀已缓存全局 KV,新 turn 50 个 token):
| 方案 | SWA 补齐代价 |
|---|---|
| V4:持久化 SWA、命中 | 0(但持续占持久缓存) |
| 精确重建 | 5120 token 过 40 层 ≈ 新 token 的 100 倍 |
| Bounded Replay | 128 token 过 40 层 ≈ 新 token 的 2.6 倍 |
两种 Replay 分工:Encoder 版面向存储(全局 KV 命中而 SWA 缺失时重放兜底,SWA 彻底退出持久缓存,体积约砍半,改存每机 10% host DRAM 的分钟级 TTL 池);Decoder 版面向计算(每次 prefill 把最后 128 个 token 的编码器输出喂过解码器 20 层,所得 SWA 仅供 decode 不缓存——支撑"prefill ≈ 编码器-only")。训练适配是共同底座:post-training 期间模拟同样的 replay;LMSYS serving 实测开启 decoder replay 后 prefill 提速 1.56×、AIME 评测零差异。
5. Single-Pass mHC:把 A 错位一层
mHC 在相邻块间维持 n 条残差流(n = hc_mult = 4):
三组系数 由系数预测器 从当前流算出。V4 的三 kernel 实现因数据依赖串行执行,含 pre-norm 总激活访存 ,是理论下界 的两倍。卡点在 :它需要扫完整 hidden 维的归约,而输入混合在本层内就要用它——每个 tile 算完只能等全维归约,然后重读 。
Single-Pass 把输入混合系数错位一个块:
层内循环变成层间接力: 的每个 tile 算完可立即同时用于输入混合、系数预测累加和 RMS 平方和累加,一次遍历完成。部署侧 Mega-mHC kernel 把残差更新、输入混合、系数预测融合进单个 kernel,精确达到 的理论下界——激活访存减半,decode 访存受限场景直接转化为时延收益。语义代价是"本层用上一层的混合权重"(相邻层流演化平滑,近似为一阶滞后),实验损失可忽略。vLLM 对应 mhc_pre_delayed_tilelang + MHC_PRE_NORM_KERNEL,Sinkhorn 迭代 20 轮。
6. Engram 与 DSpark
Engram(条件记忆):把"记忆"从计算中解耦——用 N-gram 哈希({2,3,4} 阶 × 8 哈希头)查 196B 的超大规模 embedding 表,查得的记忆向量按门控注入残差流,挂在第 1、14 层。嵌入用动量更新 + Sinkhorn 平衡优化(仅需动量缓冲,无需 Adam 的状态显存)。训练时表按行切分到专用进程组整批预取;推理时确定性寻址支持从 host 内存后台 RDMA 预取,与第一个 Transformer 块的计算重叠。图像 token 不参与 n-gram 也不注入条件记忆,n-gram 链在图像边界处打断。
DSpark(推测解码):3 个 Transformer 块的草稿 + Markov 头(rank 256)建模草稿 token 依赖 + 置信度头预测逐位置接受概率,调度器按请求动态选验证长度、最大化系统吞吐。V4.1 取消了 V3/V4 的 MTP,DSpark 是唯一推测解码方法。部署约束很有意思:PD 分离时必须双池同开——因为 prefill 池传给 decode 池的不止主模型 KV,还有 prompt 末尾 5 个 noise 槽(dspark_noise_token_id=128799)、3 个草稿块各自的 KV、目标层的注意力输入隐状态,双方记账必须逐位一致;单开一侧会导致位置错位 5 或草稿头读到空 KV。收益集中在低并发/延迟敏感场景,大 batch 下固定步开销不再回本。
7. FP4 主 KV:先证界,再省位
| 项 | 设置 |
|---|---|
| 格式 | E2M1 + 每 16 通道一个 E4M3 scale(类 NVFP4,省掉二级全局 scale) |
| 量级安全论证 | 格式上限 448×6=2688;RMSNorm 权重幅值≈1,512 维 KV latent 的 L2 范数 ≤ √512≈22.6,RoPE 保范,训练实测最大幅值约 10——余量充足 |
| 时机 | RoPE 之后量化(写入缓存时);先 RoPE 再量化只带来边际精度提升且增加 decode 开销 |
| 计算侧 | 注意力前反量化——FP4 只省存储、不要求原生 FP4 矩阵乘,跨硬件兼容 |
注意区分:专家权重的 MXFP4(32 通道 UE8M0 scale)与 KV cache 的 FP4(16 通道 E4M3 scale)是两套格式。缓存布局 448B NoPE + 128B RoPE + 8B scale = 584B/token,576B 对齐分页。
8. 总账:890 B/token 与 1/8 是怎么来的
全局 KV(常驻 HBM)= CSA2 跨层共享 × FP4:
- V4-Flash 基线 → 共享后约为其 1/2 量级(条目数骤减:编码器 3 份、解码器 1 份)
- × FP4/FP8(再减半)→ 合计约 1/4,即 890 B/token,1M 上下文 < 1 GB
持久化 KV(常驻 SSD/host)= 去掉 SWA × 全局压缩:
- SWA 约占 V4 持久缓存一半 → 去掉后 ≈ 1/2
- × 全局 KV 的 1/4 → 合计 ≈ 1/8
对应地 decode FLOPs 从 4K 到 1M 上下文仅增长 1/4(近常数),prefill 复杂度 ——架构 × 缓存精度 × 部署策略三个层面联合压低了计算、存储与带宽三本账。
回看六个设计,单项都是已有技术的组合,但组合的口径统一:凡是生命周期长于会话的(全局 KV),往死里压;生命周期短于会话的(SWA),干脆不存。这个按生命周期分治的存储哲学,比任何单项技术都更值得记住。
参考
- DeepSeek-AI 技术报告《DeepSeek-V4.1-Flash: Pushing the Limits of KV Cache Compression》(2026-09)
- HF 仓库 deepseek-ai/DeepSeek-V4.1-Flash(inference/ 目录,vLLM 实现佐证)