长上下文的代价不只在于缓存越来越多的 Key 和 Value,还在于每次 Attention 都要读取更多历史表示、计算更多 token 关系。在自回归模型的 Dense Attention 中,causal mask 让位置越靠后的 token 访问越长的历史前缀;当序列长度为 时,整个序列需要处理的 token 关系近似按 增长。
为了减少每个 Query 与历史前缀之间的 Attention 计算,最直接的思路是每次只关注部分历史位置。Sliding Window Attention(SWA)用固定窗口保留局部上下文;DeepSeek Sparse Attention(DSA)则进一步根据内容选择值得回看的位置。本文将沿着这条演进路径,解释 DSA 如何选出 token、GPU 如何只计算这些位置,以及它如何重新分配计算、读取与缓存开销。
SWA:让固定窗口沿序列移动
设当前 Query 位于 。在 Dense Attention 中,causal mask 允许它访问整个历史前缀:
SWA 则给定窗口大小 ,只保留当前位置以及最近的 个历史位置:
当 Query 从 移到 时,窗口也随之向前滑动一格。下图中的蓝色方块表示可见位置;与完整的 causal mask 相比,SWA 只保留主对角线附近的带状区域。

SWA 只改变可见范围,窗口内仍按原方式计算 Attention;窗口外的位置则被 mask 为 。可见范围缩小后,Attention 的时间复杂度从 降为 。
对于只使用局部窗口的层,Decode 时还可以淘汰窗口外的旧 KV,将该层的 KV Cache 长度从 限制为 ;如果模型中仍有保留完整前缀的 Attention 层,这些层依然需要保存全部历史。
SWA 的局限也恰恰来自固定窗口:它按距离决定保留谁,而不关心内容是否重要。 一个距离很远但与当前 Query 高度相关的 token,只要落在窗口之外,就无法被当前层直接访问;而单纯扩大 ,又会削弱稀疏计算的收益。
DSA:自适应的注意力窗口
SWA 为每个 Query 划定一段连续区间;DSA 则将这段固定窗口改为由 Query 决定的位置集合。这个“自适应窗口”不要求位置连续,可以跳过邻近 token,保留分散在上下文不同区域的相关信息。
其核心取舍是:DSA 用一次 Lightning Indexer 的全前缀扫描,换取只在 个位置上计算 Attention。

Lightning Indexer:为历史位置打分并选出 top-k
Lightning Indexer 是 Attention 前的一条可学习检索分支。它扫描 causal mask 下的完整前缀,为每个可见位置计算相关性分数,再选出得分最高的 top-k 位置。
下文使用以下记号:
- :当前 Query 的位置。
- :causal mask 下的可见位置。
- :Indexer Query head 的编号。
- 上标 :Lightning Indexer 分支。
- :Indexer 的 head 数量。
- :单个 Indexer head 的维度。
下图展开了 Lightning Indexer 从生成检索表示到选出 的完整数据流。需要注意的是,这条分支只负责决定“选谁”,不会替代随后计算 Attention 输出所用的 Query、Key 和 Value。

设 为当前 Attention 层在位置 的输入,其中 是 hidden state 的维度, 对应当前 Query。图 ① 的三条路径分别生成:
- 当前 token 的 hidden state 生成 个 Indexer Query:。
- 同一个 生成 个 head 权重:。
- 每个可见位置的 生成一个共享的 Indexer Key:。它由所有 Indexer Query head 共用,并缓存在独立的 Indexer Key Cache 中。
图中的 Query 路径先复用 MLA 的 Query latent,再通过 Indexer 专用投影生成 ;Key 路径则从各位置的 独立生成 ,不复用 MLA 的 KV latent。
在图 ② 中,对于同一个候选位置 ,每个 都与共享的历史 Key 计算点积。ReLU 截去负的点积响应,再由 对各 Indexer head 的结果加权求和:
这里的 只表示 Lightning Indexer 内部的 Query head,与后续的 Attention head 无关。汇总之后,每个可见位置对应一个标量分数 ,所有分数共同组成向量 。
图 ③ 从 中取分数最高的 个位置,得到索引集合:
由所有 Attention head 共享。Indexer 分数只决定“读取哪些位置”,不会直接成为最终的 Attention 权重;真正的 logits 与 softmax 仍会在入选位置上另行计算。
例如,设当前 Query 位于 ,并令 。如果最高的三个分数来自位置 、、,那么
随后,Sparse Attention 就只读取这三个彼此不连续位置的 KV。
Sparse Attention:在选中位置上计算 Attention
在抽象的 Attention 公式中,DSA 可以等价表示为由 决定的动态 mask,其中 表示单个 Q/K head 的维度:
这两个公式只是对 DSA 计算范围的数学描述:不在 中的位置,等价于被 mask 为 。在高效的 GPU 实现中,不会先计算完整的 Attention 分数矩阵再丢弃大部分结果,而是直接按照 给出的索引读取入选的 KV。 例如,当 时,推理框架会将这三个位置编码为 Sparse Attention 算子所需的 indices。
一个融合式 Sparse Attention 算子会根据 indices 加载对应的 KV,并直接完成 Attention 计算。换句话说,DSA 直接在选中的 个位置上计算 Attention,不会生成完整的 logits 或 Attention 矩阵,也不需要先把 KV 重新拼成一个新矩阵。
DSA 的优化效果
优化一:全局计算量优化
对于 Prefill 阶段,Dense Attention 计算 causal mask 下全部 token 关系;DSA 则为每个 Query 选择 个相关位置,再执行 Sparse Attention。下表使用一组简化记号:
| 阶段 | Dense Attention | DSA | 变化 |
|---|---|---|---|
| Lightning Indexer | - | 新增一次宽度为 的全前缀扫描 | |
| Attention | Attention 关系数从 降为 |
对于 Decode 阶段,每步只有一个新 Query。假设当前共有 个可见位置,复杂度对比如下:
| 阶段 | Dense Attention | DSA | 变化 |
|---|---|---|---|
| Lightning Indexer | - | 新增一次宽度为 的全前缀扫描 | |
| Attention | Attention 关系数从 降为 |
所以,当 保持固定且 明显小于 时,DSA 的计算优势会在上下文增长时保留下来。 它并未改变 Prefill 的 与单步 Decode 的 渐进阶数;优势来自随上下文增长的扫描宽度由 缩小为 ,同时 Sparse Attention 始终只处理每个 Query 入选的 个位置。
优化二:Decode 阶段的带宽优化
在 Decode 阶段,每生成一个 token,Dense Attention 都要从显存读取全部 个历史 KV。上下文越长,需要搬运的数据就越多,Attention 也越容易受到显存带宽限制。
DSA 将这次读取拆成两步:先扫描 个更小的 Indexer Key 选出 top-k,再只读取这 个位置的完整 KV。下表使用一组读取量记号比较每个 Query 需要读取的数据量:
| 阶段 | Dense Attention | DSA | 读取量变化 |
|---|---|---|---|
| Lightning Indexer | - | 新增一次轻量的全前缀扫描 | |
| Attention | 完整 KV 读取从 降为 |
DSA 用一次轻量的全前缀扫描,换取完整 KV 读取量从 降到 。 Dense Attention 每个 Query 的读取量为 ,DSA 则为 ;当 且 时,DSA 对显存带宽的压力更小。
在 DeepSeek-V3.2 上的优化效果
DeepSeek-V3.2 采用 。在 128K 上下文末端,每个 Query 的 Sparse Attention 只访问约 的可见位置。由论文 Figure 3 读取的每百万 token 近似成本如下:
| 阶段 | DeepSeek-V3.1-Terminus | DeepSeek-V3.2 | 成本降幅 |
|---|---|---|---|
| Prefill | $0.67 / M tokens | $0.19 / M tokens | |
| Decode | $2.15 / M tokens | $0.25 / M tokens |
小结
从 Dense Attention 到 SWA,再到 DSA,抽象的 Attention 公式没有改变;真正改变的是每个 Query 如何确定参与计算的位置:
| 机制 | 如何决定“看谁” | Attention 实际计算哪些位置 | 最关键的取舍 |
|---|---|---|---|
| Dense Attention | 不做额外筛选 | 整个可见前缀 | 不遗漏可见位置,但计算量和 KV 读取量随上下文增长 |
| SWA | 按固定距离截取 | 最近的 个连续位置 | 局部层可以淘汰旧 KV,但窗口外的重要 token 无法被直接访问 |
| DSA | Indexer 按内容打分,再取 top-k | 个可以不连续的位置 | Attention 只计算少量位置,但 Indexer 仍要扫描前缀,而且历史 KV 不能被丢弃 |
DSA 将这套选择规则直接落实到计算过程:Lightning Indexer 先扫描完整前缀并产生 ,融合式 Sparse Attention 算子再按索引读取入选 KV,只在这 个位置上完成 Attention。公式中的动态 mask 是对计算范围的等价描述,并不意味着 GPU 会先完成 Dense Attention 再丢弃结果。
因此,DSA 降低的是每次 Attention 计算和读取的历史位置数量,而不是 KV Cache 需要保留的历史长度。DSA 决定一次 Attention 读取哪些位置,MLA 决定每个位置需要缓存多少内容。 二者分别缩小访问范围与缓存宽度,并在 DeepSeek-V3.2 中组合使用。
参考资料