把 KV Cache 从 3514 字节压到 890 字节:DeepSeek V4.1-Flash 动了什么,又没动什么

长上下文 Agent 的成本,本质上只有两笔账:一次性算完 prompt 的计算量,和之后每一步都要背着的 KV 缓存。 前者随序列长度线性增长,后者要常驻显存,还要在 HBM、主机内存、SSD 之间来回搬。

上个月的普遍判断是:KV Cache 已经不是首要矛盾了------压缩到这个程度,再压的边际收益有限。

9 月 10 日,DeepSeek 用一份 51 页的技术报告回应了这件事:V4.1-Flash 把常驻 HBM 的全局 KV 从上一代的 3514 字节/token 压到 890 字节/token ;持久化 KV 压到上一代的约 1/8 ;上下文从 4K 拉到 1M(256 倍),单 token 解码 FLOPs 只增加约 25%

但这份报告最有价值的部分不是这些数字,而是它诚实地交代了三件事:解码计算量一点没省、持久化 KV 的重建是近似的、以及"缓存恢复边界"还需要更多压力测试。 这篇文章讲清楚它改了什么、没改什么,以及你的场景到底该不该上。

一、旧范式的原罪:两笔账,而且是分开的两笔

标准 Decoder-only Transformer 在长上下文下的开销来自两处,性质完全不同:

成本 复杂度 发生时机 受什么约束
Prefill(预填充) O(N·L),随序列长度 N 与层数 L 线性增长 每轮请求一次(前缀命中可省) 算力(FLOPs)
KV Cache 常驻 O(N·L·d),随上下文累积 请求整个生命周期 显存容量 + 访存带宽
Decode(解码) 每步读一遍相关 KV 每个输出 token 一次 访存带宽

关键在最后一行:解码阶段的性能瓶颈通常不是算力,而是把 KV 从显存搬进计算单元的带宽。 上下文越长,每一步要搬运的数据越多。

Agent 场景把这个矛盾放大了。一份技术报告里的表述很准确:长程 Agent 让工作负载越来越 input-heavy(输入重)------一次任务包含数百次工具调用,上下文轻松到几十万 token。于是 prefill 的计算、KV 的存储、KV 的搬运,三样一起构成部署成本的主要瓶颈。

markdown 复制代码
Decoder-only 的成本随上下文长度的变化

  成本 │
       │                                    ╱ KV 存储(线性增长 → 显存墙)
       │                              ╱
       │                        ╱
       │                  ╱
       │            ╱
       │      ╱
       │  ╱ ──────────────────────────────── Prefill 计算(线性增长)
       └────────────────────────────────────► 上下文长度
          4K                              1M

  V4.1-Flash 的目标:把这两条线的斜率都压下来

二、先把口径算清楚:890 字节到底是什么

这是最容易误读的一步。报告里的"890 字节/token"不是"这个模型的 KV 只有 890 字节",它有非常明确的限定。

2.1 每 token 的 KV 分两类

V4.1-Flash 除最前两层外,每一层都有两条注意力分支:

分支 覆盖范围 产生的 KV 随序列长度怎么变
global(全局注意力) 整个上下文 main KV (压缩后的 KV 条目)+ indexer K(供稀疏选择打分) 线性增长 ← 长上下文的大头
SWA(滑动窗口注意力) 最近 128 个 token SWA KV(窗口内未压缩) 只取决于窗口大小,恒定

890 字节/token 说的是 global 分支那两类(合称 global KV)常驻 HBM 的量。 不含 SWA KV,不含 Engram 参数,不含激活值,不含模型权重。

2.2 三级存储,各层保留策略完全不同

层级 放什么 介质 保留时长
运行时常驻 活跃请求的 global + SWA KV HBM 请求生命周期
SWA 复用池(V4.1 起新增) SWA KV,供活跃会话跨轮复用 每台机器划出的 10% 主机内存 分钟级 TTL
持久化层(persistent KV) 供跨请求复用的 KV SSD + 主机内存 ≥ 72 小时,LRU 管理

第二、三层用的是同一类介质(主机 DRAM),区别在保留策略:SWA KV 只在活跃会话的分钟级窗口里被复用,把它塞进 72 小时的前缀缓存纯属浪费。

2.3 1/4 和 1/8,是两个相乘的因子

这是整篇报告里最漂亮的一处算术,也是最容易被人混为一谈的地方:

csharp 复制代码
V4 的持久化 KV
├── SWA KV   ≈ 一半容量  →  V4.1 不再持久化(改放主机内存专用池 + 有界重放)
└── global KV ≈ 另一半   →  V4.1 用 CSA2 + FP4 压到 1/4

              1/2  ×  1/4  =  1/8
              ↑           ↑
        SWA 退出持久层    global KV 本身(架构 + 精度)

"1/4"是 global 分支 KV 本身的压缩比,"1/8"是再叠加架构层面的存储调度之后的部署结果。 两个数字都对,但说的不是同一件事。

历代对比(同口径,报告 Figure 1(b)):

代次 全局 KV(字节/token) 相对 V4-Flash
DeepSeek-V1 389,120 ---
DeepSeek-V3.2 48,068 ---
DeepSeek-V4-Flash 3,514
DeepSeek-V4.1-Flash 890 约 1/4(相对 V1 约 1/437)

还有一处常被误用的对比:vLLM 博客曾给出 V4-Pro 在 1M 上下文、bf16 下约 9.62 GiB/序列这个数字和 890 B/token 不能相除 ------前者是 61 层、bf16、含 main KV + c4a 索引器 + SWA 窗口;后者是 40 层、main KV 为 FP4、只算常驻 HBM 的 global KV。异源数字相除没有意义。9.62 GiB 的唯一用处是提供量级感:890 B/token 在 1M 上下文下不到 1 GB。

三、理论骨架:KV 成本的三个乘性维度

报告 §2.3 是全文理论价值最高的一段。它把 KV 存储拆成三个相乘的维度:

arduino 复制代码
KV 存储成本 = entry size(每个条目多大)× sequence(几个 token 压成一条)× layer(几层共用一份)
维度 怎么压 代表工作
entry size GQA 减 KV 头数;MLA 用低秩 latent 表示 GQA、MLA
sequence 每 m 个 token 压成一个条目 CSA、HCA(V4)
layer 跨层复用 KV 或索引 IndexCache、YOIO、HySparse

然后报告点名了现有跨层工作的三个缺口,这段话值得原样记下来:

  • IndexCache :复用 Top-K 索引,省下的是索引计算,不省 main KV 存储
  • YOIO :稀疏路由算一次全层共享,但全网络共享限制了性能
  • HySparse :稀疏层复用稠密层的 KV,仍是 hybrid 设计,保留了全量注意力层

结论是:没有一个是三个维度同时覆盖的。 CSA2 的主张就是三个一起上,并且把"缓存共享"和"索引复用"解耦------这两件事从此可以独立决定。

这里有一处与业界既有判断的正面冲突。此前有一种看法是:V4 压缩后单层每 token 只剩约 18 字节,跨层共享"基本无意义"------看起来确实没有压缩余地了。V4.1 给出了相反的答案:当单层的绝对量已经很小,压缩的杠杆就从"每层压多少"转向了"几层共用一份"。

四、CED:把 prefill 砍一半,代价写在同一页上

4.1 机制

CED(Causal Encoder-Decoder)的灵感来自 YoCo:让 Transformer 的上半层直接共享下半层产生的 KV。V4.1 在此基础上改了两件事------KV 的容量,以及 KV 生成的计算深度。

40 层被切成两半:

yaml 复制代码
                    Causal Encoder (20 层)              Decoder (20 层)
                 ┌─────────────────────────┐        ┌──────────────────────┐
   Embedding ───►│ 层 1-2:  SWA (窗口 128) │        │                      │
                 │ 层 3-20: CSA2           │──H²⁰──►│  global KV 由 H²⁰ 投影│──► 输出
                 │                         │  CED 桥│  SWA KV 仍逐层计算    │
                 └─────────────────────────┘        └──────────────────────┘

   Prefill: prompt token 走完 Encoder 即停 → 只需算一半层
   Decode:  生成一个 token 仍走完整 40 层

Decoder 的 global KV 不从自己的隐藏状态来,而是从 Encoder 最后一层的隐藏状态投影得到(报告式 1):

ini 复制代码
C_l = H_{L/2} · W_l^KV ,    Z_l = H_{L/2} · W_l^Z ,    l > L/2

于是 prefill 复杂度从 O(N·L) 降到近似 O(N·L/2 + n_win·L/2),长 prompt 的计算量接近减半。

config.jsonkv_source_layer_ids = [2, 8, 14, 20] 正是这四个 Full Mode 层(Encoder 三个 CSA2 组的首层 2/8/14,加上 Decoder 首层 20)------它们是各组 main KV 的生产者,字段名里的"KV 源"指的就是这个。

4.2 代价,报告自己写得很清楚

第一,Decode 计算量一点没减半。 CED 只省了 Prefill;每生成一个 token 仍然要走完整 40 层。

配套的是一组不对称激活

阶段 每 token 激活参数
Prefill 8B
Decode 16B

这个不对称是对着 Agent 负载的形态设计的------输入重、输出轻,所以 prefill 侧的激活量被单独拿出来优化。

第二,SWA 保留了逐层计算。 CED 刻意让 SWA KV 仍从每层自己的隐藏状态生成(理由是增加 SWA KV 生成的计算深度),代价是 Decoder 侧要额外处理 n_win × L/2 个 token(窗口 128,层数 40)。在短 prompt 的多轮对话里,这笔开销并不小。

这一处正是下面要讲的 SWA Bounded Replay 的由来------SWA 的每个设计决定,后面都要还。

五、CSA2:38 层里只有 8 层在真干活

CSA2(Compressed Sparse Attention 2)把每个层的角色静态分成三种模式:

模式 main KV indexer K Top-K 索引
Full 自己算 自己投影 自己跑 indexer 产生
Reindex 复用前面层 复用 用自己的 indexer Q 重打分(选择可逐层变化)
Reuse 复用 复用 复用,不跑 indexer

三种模式都自己算 main Q 和 SWA KV。

层排布:

  • Encoder 的 18 个 CSA2 层:压缩率 2,分 3 组 × 6 层(1 Full + 5 Reuse)
  • Decoder 的 20 层:压缩率 1,分 5 组 × 4 层(首组 Full + 3 Reuse;其余 Reindex + 3 Reuse)

38 个 CSA2 层里,只有 4 层产出 main KV ,另有 4 层复用 main KV 但自己重算索引 ,剩下 30 层连索引都直接复用

分层稀疏索引:把"大海捞针"变成"小池捞鱼"

scss 复制代码
第 20 层 (Full):对整个上下文打分
         │
         │  历史切成 2048 block × 8 位置 = 16,384 个候选
         ▼
   选出 Top-512 ──────► 构建 Shared Candidate Pool(固定大小)
                                   │
   后续 Reindex 层 ────────────────┘
         只在这个池内打分,不再扫描全上下文
         → 搜索规模被候选池设置"封顶",复杂度近似常数

这是"上下文涨 256 倍、Decode FLOPs 只涨约 25%"的关键之一。

CSA2 相对上一代 CSA 还做了几处简化:去掉重叠窗口、去掉绝对位置编码、indexer Key 直接从 main KV 投影得到(而不是走一条独立的隐藏状态压缩路径)------压缩路径与索引路径解耦

六、FP4 与有界重放:两个"看起来省了,其实换了东西"的设计

6.1 FP4 Main KV

设置
main KV 精度 FP4(E2M1),每 16 通道共享一个 E4M3 scale(NVFP4 去掉 global scale)
SWA KV 精度 FP8
引入方式 后训练阶段的量化感知训练(QAT)
效果 相对 V4 的 FP8 缓存,存储再降约一半

注意报告里 Decode FLOPs 那条曲线是按精度加权计算的(BF16 记 1、FP8 记 0.5、FP4 记 0.25)。所以 FP4 的引入本身就在往下压这条曲线------"只涨 25%"这个漂亮数字里,有一部分是精度换算贡献的,不全是架构功劳。

6.2 SWA Bounded Replay:持久化 KV 的重建是近似的

如果还把每层的 SWA 状态都持久化,前面省下的存储会被吃回去。V4.1 的做法是:

  1. SWA KV 不再落 SSD,改放每台机器划出 10% 主机内存的分布式池,分钟级 TTL;
  2. global KV 保留 72 小时;
  3. miss 时,用 Encoder SWA Bounded Replay 只重放最近 128 个 token 来重建,而不是重放 层数 × 窗口 个 token。

但这是近似重建。 精确重建需要把窗口通过每一层相关层重放一遍。报告称在其测试条件下退化可忽略,同时明确写道:缓存恢复边界(cache-resumption boundaries)是一个需要更多压力测试的领域。

这句话应该被每个打算在生产里依赖持久化 KV 的团队抄下来。

七、顺带一提:Engram 和另外三板斧

Engram(196B 条件记忆) :放在第 1、14 层,用 N-gram 哈希去查一张超大 Embedding 表(2/3/4-gram,每阶 8 个 hash head,每 head 约 16M 条目,FP8,放主机内存 + RDMA 预取)。思路是用查表替代重复的模式化 Attention ,把早期网络深度和 Attention 容量释放出来。官方数据:在 Multi-Query Needle-in-a-Haystack 上把分数从 84.2 提到 97.0

Single-Pass mHC :把输入混合系数提前一层,解除输入混合与系数预测的依赖,让融合 kernel 能把激活内存流量从 (4n+4)d 降到 (2n+2)d,接近理论下界。

DSpark 投机解码dspark_block_size = 5,目标层 [37, 38, 39],预训练后冻结骨干单独训练。

训练侧 :45T 多模态 token(文本:多模态 ≈ 7:1);稀疏注意力从零训练 ,64K 序列长度,无 dense warmup ;在 34T token 处把上下文扩到 1M。后训练没有新算法,增益来自大规模可验证 Agent 任务合成、跨异构 scaffold 的 RL(Claude Code / Codex / OpenCode / Pi / mini-SWE / 自研 Harness),以及 40+ 教师的 on-policy 蒸馏

八、理想丰满,现实骨感:五个工程死结

这一节决定了你该不该上,比前面所有数字都重要。

死结一:Decode 没有变便宜,变便宜的是显存

CED 只省 prefill。对"短 prompt、多轮、小输出"的典型对话场景,收益几乎全部来自 KV 压缩,而不是算力。 而这类场景本来就不受显存墙约束------它受的是首 token 延迟和单步延迟约束。

更麻烦的是:SWA 逐层计算被保留,短 prompt 下 n_win × L/2 这笔开销占比反而更高。

判据:你的负载是不是 input-heavy? 一次任务几百次工具调用、上下文几十万 token------是,CED 直接命中;几轮十几个 token 的问答------不是,你在为别人设计的约束付复杂度成本。

死结二:890 字节不会出现在你的 nvidia-smi 里

890 B/token 只算常驻 HBM 的 global KV。真实部署还要加上:SWA KV、Engram 的主机内存与 RDMA 预取开销、激活值、MoE 路由的专家参数常驻、以及框架本身的碎片。

论文数字和显存读数之间隔着一整个 serving 栈。 做容量规划时,用同代同条件的倍数(1/4、1/8)比用绝对值可靠。

死结三:稀疏注意力是近似的,Top-512 意味着绝大多数位置从未被打分

每层只读 512 个位置,而且后续 Reindex 层只在一个 16,384 的固定候选池里选。这是一个"先粗筛再精选"的结构,粗筛漏掉的,后面再也找不回来。

对"大海捞针"式的精确检索,风险是实打实的:如果那个关键信息在第 20 层的首次全量扫描里没进候选池,它在后面所有层都不会被看到。Engram 把 Multi-Query NIAH 从 84.2 提到 97.0 这个数据反过来说明------基线是 84.2,不是 100。

死结四:FP4 main KV 的精度损失没有公开的边界

main KV 量化到 E2M1(4 bit),这是通过 QAT 引入的,说明它是有损的,且需要训练配合。但报告没有给出"什么类型的任务上会崩"的公开边界。

保守做法:数值敏感、金融计算、需要精确复现长程推理链的任务,先跑自己的回归集再决定。 精度损失在 Agent 循环里会被步数复合放大------这正是我们在《4-bit 量化"几乎无损"?》那篇里讲过的同一类问题,只是这次损伤发生在 KV 而不是权重。

死结五:benchmark 口径差异大到不能混用

这是最需要警惕的一条。同一系列 benchmark,报告给出了两个差了 60 分的数字:

Benchmark V4.1-Flash 得分 对手区间 / 说明
Terminal-Bench 3.0 30.0 对手 17.7--43.3
Terminal-Bench 2.1(DeepSeek 自家 Harness) 90.5--90.6 厂商自测口径
DeepSWE v1.1 74.2 对手 66.9--74.0
CyberGym 88.1 对手 80.0--84.5
Automation-Bench 54.8 对手 45.8--50.3

版本不同(2.1 vs 3.0)、Harness 不同(第三方 vs 自家),不能直接相减 。但它说明了一件事:同一家厂商、同一个 benchmark 名字,口径差异可以造成 60 分的量级差。

官方也标注了"上述指标属于内部框架与自测口径,独立第三方评测仍待社区验证"。另外,多 Agent 的收益报告自己承认是 early results,且 wall-clock 收益"高度依赖 Harness 设计与子 Agent 隔离质量"(ProgramBench 8h:30.04% vs 单智能体 20.39%)。

九、什么场景赚,什么场景亏

赚的场景

场景 为什么赚
长程 Agent / 编码智能体(数百次工具调用) input-heavy 正对 CED 的靶心;KV 是主要瓶颈
长文档问答、代码库级检索 1M 上下文 + 890 B/token,显存不再是约束
高并发、长会话的在线服务 单会话 KV 占用降到 1/4,直接换算成并发密度
重复局部模式密集的任务(代码、结构化文档) Engram 的查表记忆命中率高

亏的场景

场景 为什么亏
短 prompt、多轮、小输出 CED 省的是 prefill,你不受 prefill 约束;SWA 逐层重算反而占比更高
数值/金融敏感任务 FP4 main KV 的有损性没有公开边界
依赖长上下文精确检索、且失败代价高 Top-512 + 固定候选池是粗筛,漏了找不回来
高度创造性、低重复的任务 Engram 的 196B 参数可能变成纯负担
想自己复现这套架构的团队 稀疏注意力需从零训练(64K,无 dense warmup)、34T token 处扩到 1M------这不是微调能解决的

决策树

css 复制代码
你的负载是 input-heavy 吗(上下文 > 100K,工具调用频繁)?
│
├─ 否 ──► 别为 CED 付复杂度成本。选一个同能力的标准架构模型,
│         把精力放在 prompt 与工具设计上。
│
└─ 是 ──► 显存是主要瓶颈吗(并发上不去 / KV 落盘)?
          │
          ├─ 否 ──► 你受的是延迟约束,CED 帮不上。先看投机解码与批处理。
          │
          └─ 是 ──► 任务对长程精确检索的容错度如何?
                    │
                    ├─ 低(法务/金融/医疗)──► 跑自己的 needle-in-a-haystack 回归集,
                    │                        重点测"关键信息不在候选池"的场景;
                    │                        同时评估 FP4 对数值任务的影响。
                    │
                    └─ 高(编码/文档/通用 Agent)──► 上。
                       并做三件事:
                       1) 用 1/4 和 1/8 做容量规划,不要用 890 B/token 绝对值
                       2) 压测缓存恢复路径(报告自己说这里需要更多测试)
                       3) 用 reasoning_effort 做成本闸门(报告称 60--80 已拿到
                          大部分 Max 能力,effort 25→100 输出 token 约 2.5 倍)

十、我的判断

第一,这不是一次"KV 压缩",是一次架构范式的回潮。 Encoder-Decoder 在 LLM 时代被 Decoder-only 打了很多年,现在它回来了,但回来得很有针对性------不是为了更好的表示学习,而是为了把"读"和"写"的成本拆开:读 prompt 走一半网络,写 token 走全部网络。这个拆分能不能成立,取决于负载是不是真的读多写少。Agent 是,聊天不是。

第二,真正的创新是"三个乘性维度同时压缩 + 缓存共享与索引复用解耦"。 此前业界的共识是单层 KV 已经压无可压、跨层共享"基本无意义"。V4.1 证明了:当单维度的边际收益耗尽,杠杆会转移到维度之间的组合方式上。这个方法论比 890 这个数字更有迁移价值。

第三,1M 上下文是能力,不是刚需。 多数业务 prompt 远不到 1M。为"能否撑住 1M"付出的架构复杂度------分层索引器、候选池、FP4 反量化内核、Engram 的 RDMA 预取------是否对你的场景划算,只能靠自己的回归集回答。别因为一个模型宣称支持 1M 就把它当成选型理由。

第四,最值得关注的下一个信号不是 KV 数字,是第三方复现。 现在所有漂亮数字都是厂商自测。等到有独立团队在非自家 Harness 上跑出 Terminal-Bench 3.0 的分数、以及有人在"缓存恢复边界"上做出压力测试,这套架构的真实边界才算被标定。在那之前,把它当成一份设计文档读,而不是一份性能保证书。


参考

  • DeepSeek-V4.1-Flash 技术报告(51 页,2026 年 9 月),模型仓库:deepseek-ai/DeepSeek-V4.1-Flash(Hugging Face,MIT 许可)。本文所有架构图与数据表均引自该报告 Figure 1(b)、Figure 2、Figure 3、Figure 4、Figure 6,并与官方 config.json 字段逐条核对。
  • 相关架构:YOCO(You Only Cache Once)、MLA(Multi-head Latent Attention)、GQA、DeepSeekMoE、NVFP4。
  • 对比工作:IndexCache、YOIO、HySparse(报告 §2.3 点名的三个跨层共享方案及其缺口)。
  • vLLM 关于 V4 在 1M 上下文下约 9.62 GiB/序列的估算(bf16、61 层、含 main KV + c4a 索引器 + SWA 窗口)------与 890 B/token 不同口径,不可直接比较。
  • 部署路径:vLLM、SGLang、Transformers;API 提供 reasoning_effort(Low=50 / High=75 / Max=100)。

免责说明:本文引用的 benchmark 数字均为 DeepSeek 官方自测口径,其中 Terminal-Bench 存在 2.1(自家 Harness,90.5--90.6)与 3.0(30.0)两个不同版本与 Harness 的结果,不可直接对比。多 Agent 相关结论报告自述为初步实验结果。独立第三方评测结果以社区复现为准。

相关推荐
锋行天下1 小时前
LangGraph 进阶:Command + Send 动态控制流、并行 Map-Reduce 实战与踩坑
人工智能
米小虾1 小时前
AI 观察:CEO 们集体喊"慢一点",钱却在加速进场
人工智能
微三云生态系统架构师-彭丹2 小时前
远方好物S2B2C系统架构:一级分销与保证金托管的合规技术实现
人工智能·算法
冬奇Lab2 小时前
DeepSeek Harness 系列(06):System Prompt 组装——动态提示词的工程实现
人工智能·deepseek
罗西的思考3 小时前
机器人模型(WM / WAM / VLA)综合分析与对比:从「看」到「想」再到「做」
人工智能·算法·机器学习
火山引擎开发者社区4 小时前
基于 AgentKit 的端到端需求交付平台:从个人提效到组织提效的 AI 落地实践
人工智能
三声三视4 小时前
75 条文章索引被一条 add 清成 1 条,退出码还是 0:tri-article 的 index.py 我读了 205 行
人工智能·ai·skill·tri-skills·tri-article
蓝速科技5 小时前
医院导诊 AI 数字人一体机场景适配与落地指南丨蓝速科技
运维·数据库·人工智能·科技·自然语言处理·技术分享
QYR-分析5 小时前
重轨受电弓行业深度报告:市场格局、技术迭代与发展前景
大数据·数据库·人工智能