Skip to content

DeepSeek DSA FLOPs ​

一句话概括:DSA 先用一个低维但仍为二次复杂度的 Lightning Indexer 找到 Top-k 个 token,再让 MLA 的核心注意力只处理这些 token,把主注意力从 O(T2) 降为 O(Tk)。

本文只推导两个部分:核心稀疏注意力和 Lightning Indexer。公式依据 DeepSeek-V3.2 Technical Report;具体张量维度和计算路径以 DeepSeek 官方的 V3.2-Exp 配置 与 Indexer 实现 为准。

Notation ​

沿用 MLA FLOPs 笔记的口径:一次 multiply-add 记作 2 FLOPs,并且只统计矩阵乘。暂时忽略 softmax、mask、normalization、RoPE、ReLU、逐元素乘法、Top-k selection 和 cache 读写。

这里还需要明确计算边界:

  • 核心注意力从已经形成的 absorbed content query QA、RoPE query QR 和 MLA cache 开始计算,不重复统计 MLA 的 query/KV projection。
  • Indexer 从 MLA 已有的 query latent CQ 和输入 hidden states X 开始计算。官方实现直接把 MLA 的 query latent 传给 Indexer,因此不再重复统计 XWDQ。
  • 不统计核心注意力之后的 latent value up-projection 和 output projection。

主要记号如下:

SymbolMeaningDeepSeek-V3.2
Tprefill / training sequence length最长 128K
tdecode 时的 KV-cache lengthvariable
k每个 query 选出的 token 数2048
dhidden size7168
h核心注意力的 query heads128
dcMLA KV latent / absorbed content dimension512
drdecoupled RoPE dimension64
dqcMLA query latent dimension1536
HIIndexer heads64
dI每个 Indexer head 的维度128

核心注意力涉及的 tensor 可以写成:

QA:(T,h,dc),QR:(T,h,dr),CKV:(T,dc),KR:(T,dr).

Indexer 涉及的 tensor 是:

CQ:(T,dqc),QI:(T,HI,dI),KI:(T,dI),WI:(T,HI).

最容易误解的一点是:KI 在所有 HI 个 Indexer heads 之间共享。因此 key projection 的 FLOPs 不乘 HI;但每个 head 都要和这份 shared key 做点积,所以 pairwise scoring 的 FLOPs 仍然乘 HI。

Causal token-pair 数 ​

Dense causal attention 实际可见的 query-key pair 数是:

Ndense(T)=T(T+1)2.

DSA 中第 s 个 query 最多保留 min(k,s) 个 key,因此核心稀疏注意力实际处理的 pair 数是:

Nsel(T,k)=∑s=1Tmin(k,s)={T(T+1)2,T≤k,kT−k(k−1)2,T>k.

第二项 k(k−1)/2 是开头不足 k 个历史 token 的 causal 修正。长序列下才可以近似写成 Nsel≈Tk。

Core Sparse Attention FLOPs ​

论文明确说明 DSA 的核心注意力采用 MLA 的 MQA mode:同一位置的 CKV 和 KR 被所有 query heads 共享。对 query s,令 Ss 是 Indexer 选出的 token 集合,ms=|Ss|=min(k,s)。

Attention score ​

content score 在 absorbed latent space 中计算:

QsA(h,dc)(CSsKV)⊤(dc,ms)→SsA(h,ms),FLOPs=2hmsdc.

RoPE score 单独走较小的 positional channel:

QsR(h,dr)(KSsR)⊤(dr,ms)→SsR(h,ms),FLOPs=2hmsdr.

两部分相加后再做 softmax。相加和 softmax 不属于本文的矩阵乘 FLOPs。

Weighted latent value ​

softmax 得到每个 query head 各自的权重 Ps:(h,ms)。所有 heads 读取同一份 latent value cache,但因为各 head 的权重不同,weighted sum 仍然要按 head 计算:

Ps(h,ms)CSsKV(ms,dc)→Zs(h,dc),FLOPs=2hmsdc.

因此,单个 query 的 core attention FLOPs 是:

Fcore,s=2hms(2dc+dr).

其中两个 dc 分别来自 content score 和 weighted latent value;dr 来自 RoPE score。

Prefill / training ​

对所有 causal query 求和:

FDSA,core,prefill=2h(2dc+dr)Nsel(T,k).

当 T>k 时:

FDSA,core,prefill=2h(2dc+dr)(kT−k(k−1)2).

如果把 Nsel 换成 Ndense,就得到相同 MQA/absorbed 路径下的 dense MLA core attention FLOPs。也就是说,DSA 并没有改变每个保留 pair 的计算,而是把 pair 数从约 T2/2 降到了约 Tk。

Decode ​

decode 时只有一个当前 query。令 m=min(k,t),则:

FDSA,core,decode=2hm(2dc+dr).

当 cache 已经长于 k 时,core attention 对上下文长度不再线性增长,而是固定为:

FDSA,core,decode=2hk(2dc+dr),t≥k.

代入 h=128、dc=512、dr=64、k=2048:

2h(2dc+dr)=278,528 FLOPs/pair.
  • 128K=131072 prefill 时,Nsel=266,339,328,core attention 约为 74.18 TFLOPs / layer。
  • 当 t≥2048 时,每个 decode token 的 core attention 是 570.43 MFLOPs / layer。

Lightning Indexer FLOPs ​

论文给出的 index score 是:

Is,r=∑j=1HIws,jIReLU(qs,jI⋅krI).

qs,jI∈RdI 是第 j 个 Indexer head 的 query,krI∈RdI 是位置 r 的 shared key,ws,jI 是当前 query 对各 Indexer heads 的组合权重。作者指出,选择 ReLU 是出于吞吐考虑;较少的 heads 和 FP8 实现使这个二次复杂度模块远轻于原始 dense attention。

Indexer projections ​

官方代码复用 MLA 的 query latent CQ 来产生 Indexer queries:

CQ(T,dqc)WIQ(dqc,HIdI)→QI(T,HI,dI),FLOPs=2TdqcHIdI.

shared Indexer key 直接从 hidden states 投影:

X(T,d)WIK(d,dI)→KI(T,dI),FLOPs=2TddI.

每个 query 还要产生 HI 个 head weights:

X(T,d)WIW(d,HI)→WI(T,HI),FLOPs=2TdHI.

所以 Indexer 的线性 projection part 是:

Findex,proj=2T(dqcHIdI+ddI+dHI).

Full-prefix index scoring ​

每个 Indexer head 都要让所有 queries 与 shared keys 做点积:

QjI(T,dI)(KI)⊤(dI,T)→AjI(T,T),FLOPs=2T2dIper head.

如果只计算 causal lower triangle,所有 HI 个 heads 的 FLOPs 是:

Findex,score,causal=HIdIT(T+1).

如果实现先形成完整的 T×T score matrix 再 mask,则是:

Findex,score,square=2HIT2dI.

ReLU、乘以 ws,jI、跨 heads 求和以及 Top-k 都不是这里统计的矩阵乘 FLOPs。特别要注意,Top-k 不会让 Indexer 的打分也变成 O(Tk):Indexer 必须先扫描整个 causal prefix,才能知道哪些位置属于 Top-k,所以它仍然是 O(T2)。

Prefill / training ​

采用 causal-aware 计数时,Indexer 总 FLOPs 是:

Findex,prefill=2T(dqcHIdI+ddI+dHI)+HIdIT(T+1).

代入 d=7168、dqc=1536、HI=64、dI=128:

Findex,prefill=27,918,336T+8192T(T+1).

对于 T=131072:

  • 三条 Indexer projection 共约 3.66 TFLOPs / layer;
  • full-prefix causal scoring 约为 140.74 TFLOPs / layer;
  • Indexer 合计约为 144.40 TFLOPs / layer,不包含 ReLU、reduction 和 Top-k。

Decode ​

decode 时只生成当前 token 的 qI、kI 和 head weights,然后让当前 HI 个 queries 扫描长度为 t 的 shared Indexer key cache:

Findex,decode=2dqcHIdI+2ddI+2dHI+2HItdI.

前三项是当前 token 的 projections,最后一项是随 cache length 增长的 full-prefix scoring。代入 DeepSeek-V3.2 参数:

Findex,decode=27,918,336+16,384t.

当 t=131072 时,Indexer 约为 2.175 GFLOPs / token / layer,其中 2.147 GFLOPs 来自扫描历史 key cache。

当前范围内的总 FLOPs ​

只把本文讨论的 core attention 与 Indexer 相加:

FDSA,prefillcore+index=2h(2dc+dr)Nsel(T,k)+2T(dqcHIdI+ddI+dHI)+HIdIT(T+1).FDSA,decodecore+index=2hmin(k,t)(2dc+dr)+2dqcHIdI+2ddI+2dHI+2HItdI.

在 128K 上,前向计算约为 218.58 TFLOPs / layer;在 t=128K 的单 token decode 中约为 2.746 GFLOPs / layer。这里的结论边界很明确:核心注意力已经从 O(T2) 变成 O(Tk),但 Lightning Indexer 仍保留 O(T2) 的全前缀打分。