arXiv'26 | FlashMemory-DeepSeek-V4:用 13.5% 的显存干 100% 的活,超长上下文推理的 less is more

FlashMemory-DeepSeek-V4:用 13.5% 的显存干 100% 的活,超长上下文推理的 less is more

插播:之前写的《动手学 AutoML》终于出版了,从 NAS 到超参优化都有覆盖,适合想系统入门 AutoML 的同学。好了广告结束,现在进入正题。

动手学AutoML书籍封面

原文:FlashMemory-DeepSeek-V4: Lightning Index Ultra-Long Context via Lookahead Sparse Attention


1. 前言

你有没有想过,当一个 LLM 在处理一段 500K token 的超长上下文时,GPU 上那些 KV cache 里有多少是真正被用到的?

答案是:90% 以上的请求,光靠最后 8K token 就能准确回答。

这就是这个领域最核心的矛盾——你为了应对那 10% 的”真需要回忆全文”的情况,不得不把整个 KV cache 全量加载到 GPU 显存里。500K token 的 context,KV cache 动辄 1.8GB+,而大部分时候你只需要其中很小一部分。

传统做法要么”全部加载”(浪费显存),要么”sliding window 只看最近的”(丢掉远处关键信息)。这两个极端,都不是答案。

今天想和大家聊聊这篇来自腾讯 AI Lab 的工作——FlashMemory-DeepSeek-V4——它在 DeepSeek-V4 的架构上做了一个非常优雅的改动:用一个超轻量的 Neural Memory Indexer,提前预测未来 64 步需要哪些历史 KV chunk,按需从 CPU 加载到 GPU,其余的全部留在 CPU 冷存储。

结果:GPU 显存占用降到 baseline 的 13.5%,准确率反而还涨了 0.6%。 对,没看错——”less is more”。500K context 下显存压缩超过 90%。

但要读懂这篇工作,你得先搞明白 DeepSeek-V4 本身的 attention 架构设计。这部分我会花较多篇幅讲清楚,因为不懂 V4 的底层,后面的 FlashMemory 就是空中楼阁。


2. DeepSeek-V4 的 Hybrid Attention 架构

先交代下背景。DeepSeek-V4 是 DeepSeek-AI 2026 年发布的最新一代大模型,分两个规格:

  • DeepSeek-V4-Pro:1.6T 参数(49B 激活),MoE 架构
  • DeepSeek-V4-Flash:284B 参数(13B 激活),MoE 架构

两者都支持 100 万 token 的上下文窗口。

这么长的 context,如果用普通的 full attention,KV cache 的线性增长会直接把 GPU 撑爆。DeepSeek-V4 的核心创新就在于它的 Hybrid Attention Architecture——把 attention 层分成两种类型,各自承担不同的任务:

2.1 HCA(Heavily Compressed Attention)

HCA 层的压缩比是 128:1

什么意思?假设原始 context 有 128K token,经过 HCA 压缩后,变成大约 1K 个 compressed entry。每个 entry 代表 128 个连续 token 的”语义摘要”。

HCA 层的作用是维持全局上下文感知——即使在超长序列下,模型也能通过这些高度压缩的 entry 感知到远处发生了什么。代价是精度有损:你知道”远处发生了某件事”,但不知道具体细节。

这些 HCA chunk 体积极小(128:1 压缩),始终保留在 GPU 显存中,不会被 offload。

2.2 CSA(Compressed Sparse Attention)

CSA 层是 DeepSeek-V4 的”精细回忆”通道。

和 HCA 不同,CSA 的压缩比低得多(保留更多 token 级细节),但不会对所有历史 token 都做 attention——它用一个 Lightning Indexer 来选择性地关注最相关的那些。

Lightning Indexer 的工作方式是:

  1. 把当前 query token 投射到一组低秩 indexer query 上
  2. 和所有历史 compressed entry 的 indexer key($K^{IComp}$)做内积
  3. 用 ReLU 激活 + Top-$k$ 选取分数最高的若干历史 entry
  4. 只对这 Top-$k$ 个 entry 做完整的 Multi-Query Attention

这样,CSA 层不需要对全量历史做 attention,只扫描 Top-$k$ 个最相关的 chunk。

2.3 MLA(Multi-head Latent Attention)

DeepSeek-V4 延续了 V3 的 MLA 设计。核心思路是对 query 和 key-value 都做低秩分解:

  • Query 先经过 down-projection 到一个低维 latent space(q_lora_rank = 1536),再 up-project 回多头
  • Key-Value 也做了类似的压缩,这样 KV cache 存储的是压缩后的 latent 向量,而不是原始的高维 KV

这个设计直接决定了 DeepSeek-V4 的 KV cache 本身就比标准 MHA 模型小很多——但在 100 万 token 下,即便压缩后,依然是线性增长的。

2.4 整体 KV cache 开销

在 1M token 上下文设置下,DeepSeek-V4-Pro 相比 V3 只需要:

  • 27% 的单 token 推理 FLOPs
  • 10% 的 KV cache

但即便如此,CSA 层的 KV cache 在 500K token 下仍然占据 1.87GB(8×H20 部署环境)。而且这个占用是不管你当前 token 用不用那些远处的 context,都全部加载

这就是 FlashMemory 要解决的问题。


3. FlashMemory 的核心思路:Lookahead Sparse Attention

FlashMemory 的设计理念是一句话:不要等用到的时候才去回忆,提前预测未来 64 步需要什么。

如下图,左侧是 DeepSeek-V4 原生的 CSA pipeline(黑线),右侧是 FlashMemory 提出的 LSA(Lookahead Sparse Attention)机制(红线):

LSA 与 CSA 架构对比

原生 CSA 的流程是:每一步 decode 都用 Lightning Indexer 做一次 Top-$k$ 选择,从全量 compressed KV 中选出最相关的 entry。这意味着所有历史 compressed KV 都要常驻 GPU 显存,否则 Lightning Indexer 没法实时做选择。

LSA 的改动看起来很小,但影响是根本性的:

  1. 引入一个 Memory Indexer,每隔 $\tau = 64$ 个 decoding step 触发一次
  2. Memory Indexer 预测:未来 64 步可能会用到哪些历史 compressed KV chunk
  3. 只把这些被预测为”关键”的 chunk 从 CPU cold pool 加载到 GPU
  4. 在这 64 步内,原生的 Lightning Indexer 在这个缩小的搜索范围内做正常的 Top-$k$ attention

这样一来,绝大部分历史 KV cache 就可以安全地留在 CPU 内存里,不占 GPU 显存。

3.1 Memory Indexer 的数学

Memory Indexer 复用了 DeepSeek-V4 原生 Lightning Indexer 的架构(低秩投影 + 内积打分),只做了一个关键改动:

把 ReLU + Top-$k$ 换成了 Sigmoid + 阈值。

原生 Lightning Indexer 的行为是:

  • ReLU 激活后取分数最高的 Top-$k$ 个 entry(固定数量)

Memory Indexer 的行为是:

  • Sigmoid 激活,把分数映射到 $(0, 1)$ 区间
  • 设定阈值 $\geq 0.5$ 的所有 entry 都被认为”关键”
  • 关键 entry 从 CPU 拉到 GPU

为什么用 Sigmoid + 阈值而不是 Top-$k$?因为不同的 query,真正需要的历史 chunk 数量是动态变化的。有些 token 只需要 local context 就够了(0 个远处 chunk),有些 token 需要综合全文(大量 chunk)。Top-$k$ 的固定数量无法表达这种差异。

具体公式:给定 decoding step $t$,当前 hidden state $\mathbf{h}_t$,先做低秩投射得到 indexer query:

\(\mathbf{c}_t^Q = \mathbf{h}_t \cdot W^{DQ}\) \(\mathbf{q}_t^l = \mathbf{c}_t^Q \cdot W^{IUQ}\)

同时计算动态 head routing weights:

\[\mathbf{w}_t^l = \mathbf{h}_t \cdot W^w\]

最终的 lookahead index score:

\[I_{t,s} = \sigma\left(\sum_{h=1}^{n_h^l} \mathbf{w}_{t,h}^l \cdot \text{ReLU}\left(\mathbf{q}_{t,h}^l \cdot (K_s^{IComp})^T\right)\right)\]

满足 $I_{t,s} \geq 0.5$ 的 entry $s$ 被加载到 GPU。

3.2 两层选择机制

FlashMemory 实际上是一个两级筛选

  1. 第一级(Memory Indexer):粗粒度,每 64 步一次,从全量历史中选出”可能需要”的 chunk 集合 $C_t^{MemComp}$,从 CPU 加载到 GPU
  2. 第二级(原生 Lightning Indexer):细粒度,每步都做,在 $C_t^{MemComp}$ 这个缩小的范围内做正常的 ReLU Top-$k$ 选择,得到最终参与 attention 的 $C_i^{CoreComp}$

这种分层设计保证了:即使 Memory Indexer 的 recall 不完美,只要关键 chunk 被”宽松地”装进 GPU,原生的精确选择机制仍然能正常工作。


4. 训练:一张 H20 卡训一小时

这是这篇工作最让我印象深刻的地方。

Memory Indexer 的训练和整个 backbone 完全解耦。具体来说:

关键洞察:历史 entry 的 compressed indexer key $K_s^{IComp}$ 是在 backbone forward 时预计算好的、完全固定的。训练 Memory Indexer 本质上只是在训练一个 dual-encoder 的 query encoder——把当前 hidden state 映射到一个能正确匹配固定 key 的空间。

训练 pipeline:

  1. 离线跑一遍 DeepSeek-V4-Flash backbone,收集每个 token 的 hidden state 和 indexer key
  2. 构造 golden label(哪些 entry 是”真正需要的”)
  3. 只训练 query 端的低秩投影矩阵($W^{DQ}$, $W^{IUQ}$, $W^w$),用 Focal Loss

训练过程中 完全不加载 backbone 模型。参数量不到整个模型的 0.1%。

结果:在一张 H20 上跑 1 小时就收敛了。 8 张 H20 一周跑了 500 次实验扫参数空间。

这比传统的 end-to-end self-distillation(原生 Lightning Indexer 的训练方式)快了不知道多少个量级。

4.1 Golden Label 怎么造

直接用原生 Lightning Indexer 的 Top-$k$ 选择结果作为 label 会有严重的 inflation 问题——Top-$k$ 是固定数量的,不管这个 entry 有多不相关都会被选上。

FlashMemory 提出了 Cross-Layer Majority Voting 去噪:

  1. 对未来 window $[t, t+\tau-1]$ 内的每个 token $i$,收集 21 层 CSA 的原始 indexer logit
  2. 对每层做 Softmax + Top-$p$($p=0.6$)动态截断(而非固定 Top-$k$)
  3. 跨层投票:只有在 $\geq 3$ 层中都被独立选中的 entry 才认为是”golden”
  4. 对整个 window 取 union 作为最终正样本集合

这个 pipeline 把原始的约 10,000 个 pseudo-positive 过滤到 100-1,000 个 high-confidence entry。

4.2 最优配置:3 层就够了

并不是每一层 transformer 都适合做 lookahead prediction。浅层的表示主要是 low-level token statistics,做长程预测效果差。

通过 500 次 Pareto 优化,最终确定在 第 10、12、20 层 放置独立的 Memory Indexer,用 OR-mode 路由(三层中任何一层预测 $\geq 0.5$,就加载该 chunk)。

用 8 层?recall 太宽松,会把 30-49% 的历史 chunk 加载回来,失去了省显存的意义。用 1 层?代表能力不够。3 层是 sweet spot。


5. 实验结果

主实验结果

在三个主要长上下文 benchmark 上(LongBench-v2、LongMemEval、RULER):

指标 DS-V4-Flash FM-DS-V4 Recency Only Random 10%
平均准确率 76.9% 77.5% (+0.6) 33.3% 38.7%
平均显存 0.93 GB (100%) 0.10 GB (13.5%) 0.04 GB 0.12 GB

几个关键数字:

  • LongBench-v2-L(493K context):FM-DS-V4 在只用 10% 显存的情况下比 baseline 高了 1.9 分。Less is more 在这里被最极端地验证——去掉噪声 chunk 反而减少了 attention 中的干扰
  • RULER 512K:89.6 vs 88.3,FM-DS-V4 用 0.18GB vs baseline 的 1.87GB,显存压缩超过 90%
  • Recency Only 和 Random 10% 全面崩溃(准确率只有 baseline 的一半不到),说明 Memory Indexer 确实学到了有意义的 temporal routing,不是随机碰运气

如下图是性能和显存的直观对比:

性能与显存效率对比


6. 局限性:不是万能的

这篇工作非常坦诚地列出了三个 failure case,我觉得这比单纯报正面结果有价值得多。

6.1 Context-Independent Overhead

理想状态下,如果当前 query 和历史 context 完全无关,Sigmoid gating 应该输出接近零的分数,不加载任何 chunk。但实际上 Sigmoid 存在”背景泄漏”——在 500K context 下,模型还是会误加载约 8.4% 的历史 chunk(虽然准确率没受影响)。

6.2 MRCR 崩溃(Dense Global Memory 任务)

在 Multi-Range Context Retrieval(MRCR)benchmark 上,准确率从 baseline 的 76.0% 暴跌到 48.0%

原因:MRCR 要求模型同时精确回忆分散在全文多个位置的信息——这是一个”dense global memory”任务。即便给 oracle 50% 的 golden chunk,准确率也会下降 2%。这说明某些任务天生就不适合 sparse 策略,它们需要”全量密集记忆”。

Memory Indexer 基于浅层 dot-product 相似度做决策,缺乏 Late-Interaction(如 ColBERT 式 token 级交互),面对这类复杂的多点检索任务,能力有限。

6.3 长度泛化天花板

Memory Indexer 只能安全泛化到训练长度的 2 倍。超过这个边界,lookahead 选择退化为接近随机。作者把最终模型训练到 512K,推测超过 1M 就会失效。

本质原因是 positional embedding 的 out-of-distribution——这不是一般的检索模型,它依赖位置信息来建模”远处 vs 近处”的优先级。


7. 我的看法

先说我觉得好的部分。

“Backbone-free decoupled training”是这篇工作最值得学习的工程范式。 把一个复杂系统的优化分解为:固定 key representation + 只训 query encoder,这样一来训练成本从”需要加载整个千亿参数模型”变成”单张 H20 一小时”。这个思路对很多 retrieval-augmented 的系统设计都有启发意义。

Less is more 的实验结果很有意思。 FM-DS-V4 在 LongBench-v2-L 上不仅没掉点还涨了 1.9%,说明原生 full attention 确实存在”注意力噪声”问题——太多不相关的 chunk 参与 attention dot-product 会干扰模型决策。这个发现和 sparse attention 文献中的 “attention denoising” 观察一致。

但项目被暂停是遗憾的。 论文明确说了因为组织调整(project lead 离开腾讯),项目已经 suspended。很多关键 ablation 没做完——$\tau=64$ 和阈值 0.5 都是初步探索的值,没有系统对比。MRCR 上的 failure 也没来得及修(作者提出了 Late-Interaction 方向但未验证)。

从实际 serving 角度看,FlashMemory 的价值在于:如果你的业务以”长 context 但大部分回答不需要精确全文回忆”为主(这是绝大多数 RAG/agent 场景),那么它能用极低的显存服务超长 context。但如果你的场景是”必须精确检索全文多个位置的信息”(MRCR 类任务),目前的 Memory Indexer 还不够。

代码和模型都已开源:GitHub / HuggingFace。值得拉下来看看 Memory Indexer 的实现细节。


欢迎评论区交流,或者指出理解有偏差的地方。