从线性注意力到 KDA:拆解 Kimi K3 的核心注意力机制

本文主要基于 Moonshot AI 发表的技术报告 Kimi K3: Open Frontier Intelligence(arXiv 2607.24653)整理,架构细节部分参考了 MoonshotAI/Kimi-K3 的模型卡与 José David Baena 的架构解析文章 Inside Kimi K3。线性注意力的演化脉络参考了 RetNet、GLA(Gated Linear Attention)、DeltaNet 等公开论文。文中数字如无特别说明均引自官方技术报告,第三方评测口径已在文中标注。

Kimi K3 是 Moonshot AI(月之暗面)2026 年 7 月发布的旗舰模型:2.8T 总参数、104B 激活参数的原生多模态 MoE 模型,号称"全球首个开源 3T 级模型"。它在架构上最显眼的变化,是把主力注意力机制从纯 MLA 换成了 KDA(Kimi Delta Attention)+ Gated MLA 的混合结构。KDA 属于"线性注意力"家族,但它的公式里混着衰减门、delta rule、chunkwise 并行——单看论文公式很容易卡住。本文按"是什么 → 为什么这么设计 → 数学怎么推 → 怎么在 GPU 上并行"的顺序,把 KDA 从线性注意力的起点一路推到 Kimi K3 实际落地的 kernel 设计,再讲清楚跟 KDA 搭档的 Gated MLA 层解决的是哪一个 KDA 解决不了的问题。

一、Kimi K3 是什么

在深入注意力机制之前,先看一下整体定位和规格。

规格项 数值
总参数 / 激活参数 2.8T / 104B
层数 93(69 KDA + 24 Gated MLA)
注意力隐藏维度 / 头数 7168 / 96
专家数 / 激活数 / 共享专家 896 / 16 / 2(稀疏度 56)
上下文长度 1,048,576(1M)
词表 160K
视觉编码器 MoonViT-V2,401M 参数,27 层
量化 MXFP4 权重 / MXFP8 激活(QAT)

对比上一代 Kimi K2:层数 61→93,总参数 1.04T→2.78T,激活参数 32.6B→104.2B,专家数 384→896,训练上下文 128K→1M,注意力从纯 MLA 换成 KDA + MLA 混合,激活函数从 SwiGLU 换成自研的 SiTU-GLU。官方给出的整体 scaling efficiency 提升约 2.5×

官方在报告中的自我定位是:综合能力仍落后于 Claude Fable 5 和 GPT-5.6 Sol,但领先其余开源 / 闭源模型;在 WebDev Arena 上以 1678 Elo 排名第一,是首个登顶该榜的开源模型。

这些指标背后最关键的架构改动,就是本文要拆解的 KDA。要理解 KDA,得先回到"线性注意力"这个更大的概念。

二、标准注意力贵在哪:为什么需要线性注意力

标准(softmax)因果注意力的核心公式是:

ot=itexp(qtki)vi/itexp(qtki)o_t = \sum_{i \le t} \exp(q_t \cdot k_i)\, v_i \Big/ \sum_{i \le t} \exp(q_t \cdot k_i)

问题出在相似度函数 exp(qtki)\exp(q_t \cdot k_i) 上:指数函数把 qqkk "缠"在了一起,没办法写成 f(qt)g(ki)f(q_t) \cdot g(k_i) 这种"各算各的,最后再乘起来"的可分解形式。正因为拆不开,每个 tt 都必须和所有 iti \le t 挨个算一遍相似度——这是 O(n2)O(n^2) 复杂度的来源,也是为什么必须把每个历史 token 的 ki,vik_i, v_i 存下来,也就是随长度线性增长的 KV cache。

三、线性注意力的推导:把 softmax 换成可分解核

Linear Attention(Katharopoulos et al., 2020,论文标题就是《Transformers are RNNs》)的思路是换一个能写成两个独立特征映射内积的相似度函数:

sim(qt,ki)=ϕ(qt)ϕ(ki)\text{sim}(q_t, k_i) = \phi(q_t)^\top \phi(k_i)

这样一换,qtq_t 就能被合法地搬到求和符号外面:

ot=itϕ(qt)ϕ(ki)vi=ϕ(qt)itϕ(ki)vi=:Sto_t = \sum_{i \le t} \phi(q_t)^\top \phi(k_i)\, v_i = \phi(q_t)^\top \underbrace{\sum_{i \le t} \phi(k_i)\, v_i^\top}_{\displaystyle =: S_t}

StS_t 是一个 dk×dvd_k \times d_v 的矩阵,累积了"历史 key-value 外积之和",并且可以写成递推形式:

St=St1+ϕ(kt)vtS_t = S_{t-1} + \phi(k_t)\, v_t^\top

这正是"线性注意力"名字的来源:① 相似度函数可分解(不是指数核);② 因为可分解,整套计算能重写成一个逐步累加的线性递推,复杂度从 O(n2)O(n^2) 降到 O(n)O(n),状态大小固定,不随序列长度增长。这个递推形式在数学上等价于 RNN 的隐状态更新——这也是"Transformers are RNNs"这个标题的含义。

一个最小例子:假设 dk=dv=1d_k=d_v=1,历史 (k1,v1)=(2,5)(k_1,v_1)=(2,5)(k2,v2)=(3,7)(k_2,v_2)=(3,7),当前 query q3=4q_3=4ϕ\phi 取恒等映射。

标准做法:o3=q3k1v1+q3k2v2=4×2×5+4×3×7=40+84=124o_3 = q_3k_1v_1 + q_3k_2v_2 = 4\times2\times5 + 4\times3\times7 = 40+84=124

线性注意力做法:先算 S2=k1v1+k2v2=10+21=31S_2 = k_1v_1+k_2v_2 = 10+21=31(与 q3q_3 无关,可提前维护),再算 o3=q3S2=4×31=124o_3 = q_3 \cdot S_2 = 4\times31=124。结果一样,但状态 S2S_2 可以被复用——这就是效率提升的来源。

四、朴素线性注意力的缺陷,以及到 KDA 的演化线

St=St1+ϕ(kt)vtS_t = S_{t-1} + \phi(k_t)v_t^\top 有个明显缺陷:只会加,从不减。历史 token 无论多久之前都以同等权重永久留在状态里,模型无法学会"这条信息不重要,可以淡出",长序列下新旧信息互相稀释,效果通常明显不如 softmax attention。这条缺陷催生了一整条"如何给线性注意力加遗忘机制"的研究线,最终汇聚到了 KDA。

方法 状态更新公式 遗忘机制 写入方式
标准 Attention 无固定状态,存全部 KV 靠 softmax 权重隐式实现
朴素 Linear Attention St=St1+ktvtS_t = S_{t-1} + k_tv_t^\top 直接累加
RetNet St=γSt1+ktvtS_t = \gamma S_{t-1} + k_tv_t^\top 全局固定衰减率 γ\gamma 直接累加
GLA St=diag(αt)St1+ktvtS_t = \text{diag}(\alpha_t) S_{t-1} + k_tv_t^\top 逐通道、输入相关 直接累加
DeltaNet St=(Iβtktkt)St1+βtktvtS_t = (I-\beta_tk_tk_t^\top)S_{t-1} + \beta_tk_tv_t^\top 无衰减 纠错式(先减冲突项再写)
KDA St=(Iβtktkt)diag(αt)St1+βtktvtS_t = (I-\beta_tk_tk_t^\top)\text{diag}(\alpha_t)S_{t-1} + \beta_tk_tv_t^\top 逐通道、输入相关 纠错式

从这张表可以看出,KDA 本质上是把 GLA 的"逐通道遗忘"和 DeltaNet 的"纠错式写入"这两条独立发展的思路合并到一起,再叠加若干工程改造。也正因为血统来自 DeltaNet,它才叫 “Delta Attention”。

五、KDA 完整数学结构

5.1 Delta Rule:用"纠错"取代"叠加"

DeltaNet 的思路借用了经典的 Widrow-Hoff Delta Rule。写入新的 (kt,vt)(k_t,v_t) 之前,先问一句:如果现在拿 ktk_t 去查现有的表 St1S_{t-1},能查出什么?

vpred=St1kt,et=vtvpredv_{\text{pred}} = S_{t-1}^\top k_t, \qquad e_t = v_t - v_{\text{pred}}

只把这个误差写进表里,写入强度由 βt(0,1)\beta_t \in (0,1) 控制:

St=St1+βtktet=St1+βtktvtβtktktSt1S_t = S_{t-1} + \beta_t k_t e_t^\top = S_{t-1} + \beta_t k_t v_t^\top - \beta_t k_t k_t^\top S_{t-1}

整理后:

St=(Iβtktkt)St1+βtktvtS_t = \big(I - \beta_t k_t k_t^\top\big)\, S_{t-1} + \beta_t k_t v_t^\top

βtktvt\beta_t k_t v_t^\top 是"把误差写进去",(Iβtktkt)St1(I-\beta_tk_tk_t^\top)S_{t-1} 是"旧表在这个方向上先被清掉一部分,避免新写入和旧记忆打架"。这比朴素线性注意力的无脑叠加稳定得多。

5.2 加上逐通道遗忘门

Delta rule 本身没有主动遗忘机制。KDA 在写入前,对旧状态先做一次逐通道衰减:

St=(Iβtktkt)Diag(αt)St1+βtktvtS_t = \big(I - \beta_t k_t k_t^\top\big)\, \text{Diag}(\alpha_t)\, S_{t-1} + \beta_t k_t v_t^\top

αt(0,1)dk\alpha_t \in (0,1)^{d_k} 是一个向量,对状态的每个通道单独乘一个衰减系数——类似 LSTM 遗忘门,但是逐通道、输入相关,模型可以让"语法结构"这类需要记很久的信息衰减得慢,让临时信息衰减得快。整个更新可以概括为四步:① 旧记忆按通道各自淡忘一点;② 检查新 key 是否与已有记忆冲突,冲突部分先抹掉;③ 写入新的 key-value 关联;④ 用 query 查表得到输出。

5.3 参数是怎么算出来的

qth,kth=L2Norm(Swish(ShortConv(Wq/khxt))),vth=Swish(ShortConv(Wvhxt))q_t^h, k_t^h = L_2\text{Norm}(\text{Swish}(\text{ShortConv}(W_{q/k}^h x_t))), \qquad v_t^h = \text{Swish}(\text{ShortConv}(W_v^h x_t))

q,kq,k 先经过局部短卷积(ShortConv)→ Swish 激活 → L2 归一化(归一化让 ktk_t 成为单位向量,ktktk_tk_t^\top 因此是一个几何意义清晰的投影矩阵);vv 同样过短卷积 + Swish,但不归一化,以保留数值大小信息。βt\beta_t 由一个线性层接 Sigmoid 得到,αt\alpha_t 由一个低秩投影 + 逐头 bias 算出衰减 logit 后再映射得到。

5.4 下界衰减:一个纯工程动机的数学改动

如果 ztαtz_t \to \alpha_t 的映射没有下界(上一代 Kimi Linear 用 negative-softplus,α\alpha 理论上可无限趋近 0),chunkwise 并行算法(第七节)里会用到"累积衰减的倒数" 1/Γ1/\Gamma。当很多个小于 1 的 α\alpha 连乘趋近 0 时,倒数会趋向无穷大,在 BF16 下直接数值溢出。

Kimi K3 把衰减映射换成缩放 Sigmoid,把 logα\log\alpha 限制在固定下界 5-5 以内:

αth=exp(gminSigmoid(eAhzth))(e5,1)dk\alpha_t^h = \exp\big(g_{\min}\,\text{Sigmoid}(e^{A_h} z_t^h)\big) \in (e^{-5}, 1)^{d_k}

倒数因此永远不超过 e5e^5 量级,落在 BF16 安全范围内,使所有 tile(包括后面会讲的对角 tile)都能走密集 Tensor Core 矩乘。这是一个典型的"数学表达式为硬件效率让步"的设计。

5.5 输出门

读出结果 o~t=Stqt\tilde o_t = S_t^\top q_t 还要过一个输入相关的全秩门才输出:

yt=Wo[Sigmoid(Wgxt)RMSNorm(o~t)]y_t = W_o \big[\text{Sigmoid}(W_g x_t) \odot \text{RMSNorm}(\tilde o_t)\big]

门的开合程度由当前输入 xtx_t 决定,逐通道控制"这次从记忆里查出的信息要放多少进最终输出"。

六、KDA 的结构图

先看 KDA 在整个 Block 里的位置:Kimi K3 每个 Block 由 3 层 KDA + 1 层 Gated MLA 组成,反复堆叠 23 次,最后再补 1 层 MLA。

再看单个 KDA 层在时间步 tt 的内部数据流:

图中左侧四条竖线是四个并行的参数生成分支(q,k,v,β,αq,k,v,\beta,\alpha),中间的状态更新链是递归的核心——必须等前一个 token 算完 St1S_{t-1} 才能继续,这也是为什么需要专门设计 chunkwise kernel 来加速它。虚线箭头(StSt1S_t \to S_{t-1})表示状态矩阵原封不动地带到下一个 token,大小永远不变,这正是 KDA 相对于普通 KV cache 注意力最大的不同点。

七、Chunkwise 并行:把串行递推重写成矩阵乘法

上面的递推是逐 token 串行的,在 GPU 上效率很低——GPU 偏好大矩阵乘法,不喜欢一步一步的小计算。论文给出的解法是把序列切成 chunk(设 chunk size 为 CC),chunk 内尽量用矩阵乘法并行,chunk 间才通过状态串行传递。推导分三步递进。

7.1 无衰减、无纠错(热身)

递推 Si=Si1+kiviS_i = S_{i-1}+k_iv_i^\top 展开后 Si=S0+jikjvjS_i = S_0 + \sum_{j\le i}k_jv_j^\top,代入 oi=Siqio_i=S_i^\top q_i,写成矩阵形式(Q,K,VQ,K,V 是把 qi,ki,viq_i,k_i,v_i 按行堆叠成的 C×dC\times d 矩阵):

O=QS0跨chunk项+Tril(QK)Vchunk内项,SC=S0+KVO = \underbrace{QS_0}_{\text{跨chunk项}} + \underbrace{\text{Tril}(QK^\top)V}_{\text{chunk内项}}, \qquad S_C = S_0 + K^\top V

chunk 内的部分其实就是一次普通的带因果 mask 的矩阵乘法,这正是线性注意力能"变回"矩阵乘法的关键。

7.2 加上逐通道衰减

定义累积衰减 γi=α1αi\gamma_i = \alpha_1\odot\cdots\odot\alpha_i,展开可得 Si=diag(γi)S0+jidiag(γi/γj)kjvjS_i = \text{diag}(\gamma_i)S_0 + \sum_{j\le i}\text{diag}(\gamma_i/\gamma_j)k_jv_j^\top。把衰减挪到 q,kq,k 身上分别做缩放:

Q~:=QΓ1C,K~:=K/Γ1C\tilde Q := Q \odot \Gamma^{1\to C}, \qquad \tilde K := K / \Gamma^{1\to C}

剩下就是普通点积,O=Q~S0+Tril(Q~K~)VO = \tilde QS_0 + \text{Tril}(\tilde Q\tilde K^\top)V。这也是第五节要专门做"下界衰减"的原因——Γ\Gamma 出现在分母里,必须保证它不会数值溢出。

7.3 加上 delta 纠错项(真正的难点)

完整递推 Si=(Iβikiki)Si1+βikiviS_i = (I-\beta_ik_ik_i^\top)S_{i-1} + \beta_ik_iv_i^\top 没法像前两步一样简单展开,因为 (Iβikiki)(I-\beta_ik_ik_i^\top) 直接作用在 Si1S_{i-1} 上,而 Si1S_{i-1} 本身包含之前所有 token 的纠错历史。

猜测最终解具有类似结构:Si=S0+jikjujS_i = S_0 + \sum_{j\le i}k_ju_j^\top,其中 uju_j 是"修正后的 value"。代入递推并比较系数,可得:

ui=βi[viS0kij<i(kikj)uj]u_i = \beta_i\Big[v_i - S_0^\top k_i - \sum_{j<i}(k_i\cdot k_j)u_j\Big]

这个式子对 uju_j 是线性的,系数 (kikj)(k_i\cdot k_j) 可以用一次矩阵乘 KKKK^\top 全部提前算出来,于是"求所有 uiu_i"等价于解一个三角线性方程组。令 L=StrictLowerTri(KK)L=\text{StrictLowerTri}(KK^\top)B=diag(β)B=\text{diag}(\beta)

(I+BL)U=B(VKS0)(I+BL)\,U = B(V-KS_0)

I+BLI+BL 是对角线全 1 的下三角矩阵,保证可逆,且能用前向替换 / 分块递归并行求解。利用方程的线性性,把 S0S_0 的依赖单独剥离:

U:=(I+BL)1BV,W:=(I+BL)1BK,V~:=UWS0U := (I+BL)^{-1}BV, \qquad W := (I+BL)^{-1}BK, \qquad \tilde V := U - WS_0

这正是论文中"UT transform 产出 UUWW"——U,WU,W 完全不依赖 S0S_0,只用到本 chunk 内的 Q,K,V,βQ,K,V,\beta,可以对所有 chunk 提前并行算好,不必等前一个 chunk 算完。算好之后只需一步矩阵减法把 S0S_0 接回来。最终套用第一步的框架:

O=QS0+Tril(QK)V~,SC=S0+KV~O = QS_0 + \text{Tril}(QK^\top)\tilde V, \qquad S_C = S_0 + K^\top\tilde V

(叠加第二步的衰减重标度后,就是论文公式里完整的 A[t],V~[t]A_{[t]}, \widetilde V_{[t]}。)

7.4 手算验证

C=2C=2,标量情形,忽略衰减,S0=0S_0=0k1=1,v1=5,β1=0.5k_1=1,v_1=5,\beta_1=0.5k2=1,v2=7,β2=0.4k_2=1,v_2=7,\beta_2=0.4

逐步递推:S1=0.5×5=2.5S_1 = 0.5\times5=2.5S2=0.6×2.5+0.4×7=1.5+2.8=4.3S_2 = 0.6\times2.5+0.4\times7=1.5+2.8=4.3

三角求解:L=(0010)L=\begin{pmatrix}0&0\\1&0\end{pmatrix}I+BL=(100.41)I+BL=\begin{pmatrix}1&0\\0.4&1\end{pmatrix}BV=(2.5,2.8)BV=(2.5,2.8),解得 u1=2.5u_1=2.5u2=2.80.4×2.5=1.8u_2=2.8-0.4\times2.5=1.8S2=k1u1+k2u2=2.5+1.8=4.3S_2 = k_1u_1+k_2u_2=2.5+1.8=4.3。两种算法结果一致。

7.5 为什么这样改写更快

逐 token 串行算法 Chunkwise 矩阵算法
串行步数 nn(每个 token 一步) n/Cn/C(每个 chunk 一步,CC 通常几十到上百)
每一步操作对象 整个状态矩阵 dk×dvd_k\times d_v(如 128×128) C×CC\times C 三角方程组(如 64×64),远小于状态矩阵
主要计算形式 无法用矩阵乘法表达 全是 GEMM + 一次三角求解,都是 GPU 强项

真正必须串行的部分被压缩到解一个很小的三角方程组,剩下所有大矩阵运算都变成可以一次性铺开的并行矩阵乘法。chunk 之间仍需把 SCS_C 传给下一个 chunk 作为 S0S_0,但这层递归已经从"每个 token 一步"降到"每个 chunk 一步"。如果序列长到要分布在多个 GPU 上,chunk 间 / rank 间的这层递归就是 KDA Context Parallelism(KCP)要解决的问题:它用一次 all-gather,把每个 rank 本地算好的状态和转移矩阵传播出去,避免真的排队等待。

八、Tile 级并行:进一步压缩串行深度

论文的实际 kernel(FlashKDA)还会把一个 chunk 再切成更小的 16-token tile,tile 内部走"直接计算",tile 之间走矩阵乘法。这其实是同一个"跨块 + 块内"套路,在更小的粒度上又用了一次。

每个 tile 内部还是要按 token 顺序做局部纠错计算——这部分是 delta rule 天生自带的串行内核,躲不开,但因为 tile 只有 16 个 token,规模固定且很小。tile 之间的修正只需要拿前面 tile 已解出的 uu 值,做一次稠密矩阵乘法,这是 Tensor Core 最擅长的运算,几乎不构成瓶颈。

对照来看,"序列 → chunk"和"chunk → tile"用的是完全相同的模式:内部(对角)做小规模直接计算,之间(非对角)用固定大小的状态或矩阵乘法传递。这种"用小状态串联、中间全用矩阵乘法覆盖"的思路本质上是递归自相似的,理论上可以一直切下去(对应数值线性代数里的分块前向替换,或者线性递推的并行前缀扫描,深度可以降到 O(logC)O(\log C))。但工程上在 16 token 这个粒度就停下来,是因为每多切一层都要多一次调度开销,而 16 个 token 的直接计算已经足够便宜——继续细分收益有限,实现复杂度却会上升,最终是数学并行度与工程简单度之间的一个实用平衡点。

九、Gated MLA:KDA 之外的全局交互层

KDA 解决了"序列方向怎么高效检索历史 token",但它把整段历史压进一个固定大小的状态矩阵,本质上是有损压缩——写入越多,早期精确信息被冲刷、被近似的风险就越大。Kimi K3 的 Hybrid Attention 因此没有把 KDA 用到底,而是每 3 层 KDA 后插 1 层 Gated MLA,靠它保留一条**无损、全局、O(n2)O(n^2)**的精确检索通路。理解 Gated MLA,要拆成三件事:MLA 本身怎么压缩 KV、为什么它不需要位置编码(NoPE)、"Gated"这个前缀又是什么。

9.1 MLA:把 KV 压缩到低维 latent,而不是丢弃

MLA(Multi-head Latent Attention,源自 DeepSeek-V2)解决的是标准 attention 的另一个开销——KV cache 随上下文线性增长。它的做法不是像 KDA 那样放弃精确检索换固定状态,而是把每个 token 的 key/value 表示压缩进一个低维 latent 向量

ct=Wcxt\bm{c}_t = \mathbf{W}_c \bm{x}_t

只缓存这个低维的 ct\bm{c}_t,不缓存每个 head 各自的完整 k,vk,v;真正做 attention 时,再用学到的 up-projection 矩阵从 ct\bm{c}_t 里重建出各 head 的 content key 和 value。缓存体积因此大幅缩小,但依然是对全部历史 token 做完整的 softmax attention——检索仍然是精确的、无损的,牺牲的只是缓存的存储形式,不是信息本身。

这正是"KDA + MLA 混合"里两者分工的关键:KDA 用固定状态换来 O(n)O(n) 的效率,但检索是近似的;MLA 保留 O(n2)O(n^2) 的精确全局检索,只在缓存形式上做压缩。周期性插入 MLA,就是在"效率优先的近似检索"里定期插入一次"不打折扣的精确检索",防止 KDA 的有损状态在长序列下累积误差、丢掉早期的关键信息。

9.2 NoPE:为什么 MLA 层反而不需要位置编码

标准 attention 的 softmax 是排列不变的——不额外告诉它 token 顺序,它分不出"第 1 个 token"和"第 100 个 token"的区别,这也是为什么正常 Transformer 都要在 Q、K 上加 RoPE 之类的位置编码。但 Kimi K3 的 MLA 层完全不加任何显式位置编码,这就是 NoPE(No Position Encoding)

能这么做的原因,恰恰是因为 MLA 不是独立工作的——它嵌在 KDA 层中间。KDA 本身是一个依赖顺序的循环过程:状态 StS_t 的更新天然携带"这是第几步""衰减了多少"这类位置和时效信息,这些信息在 KDA 层处理完之后,已经隐式编码进了送往下一层的隐藏表示里。等这份表示流转到 MLA 层时,位置信息已经"自带"在内容里了,MLA 不需要再单独注入一份显式的位置编码——它只管做基于内容的全局检索,位置感知的活儿完全交给旁边的 KDA 层

这个设计带来一个实际的工程好处:因为 MLA 层压根没有显式的位置编码参数,扩展上下文长度时不需要重调 RoPE 的频率基数,也不需要套用 YaRN 之类的插值方案——没有这类参数,自然没有"参数要不要重调"的问题。

9.3 Gated:让每个 token 自己决定读多少全局信息

"Gated MLA"的 Gated 前缀,说的是 K3 在 MLA 原始输出之外,又加了一层输入相关、逐通道、全秩的输出门

yt=Wo[Sigmoid(Wgxt)o~t]\bm{y}_t = \mathbf{W}_o\big[\text{Sigmoid}(\mathbf{W}_g \bm{x}_t) \odot \tilde{\bm{o}}_t\big]

o~t\tilde{\bm{o}}_t 是没加门控之前 MLA 的原始输出,Wg\mathbf{W}_g 是一个全秩的门投影矩阵——跟 KDA 输出门用的是同一套参数化方式(KDA 一节的输出门 yt=Wo[Sigmoid(Wgxt)RMSNorm(o~t)]y_t = W_o[\text{Sigmoid}(W_gx_t)\odot\text{RMSNorm}(\tilde o_t)],两者结构几乎一模一样,只是 MLA 这边没有额外的 RMSNorm)。直觉上,这个门让每个 token 可以按自己的内容,逐通道地决定"这次从全局 attention 里查到的信息,每个维度要放多少进最终输出",而不是无条件把 MLA 算出来的东西全盘接收。

9.4 一个训练细节:为什么 attention 输出要保持 FP32

Flash attention 在低精度下存在一个有偏的舍入误差,K3 沿用已有方法,在训练时把 attention 输出保持在 FP32——这会让输出 tile 的片上(on-chip)显存占用翻倍。为了不因此挤占宝贵的 shared memory,团队把这份多出来的显存开销安排去跟 KV staging buffer 重叠,而不是跟 query tile 重叠,腾出空间给更深的 KV pipeline,换取更高的训练吞吐。这是一个典型的"先解决数值正确性,再把因此产生的额外开销想办法用调度技巧藏起来"的例子。

十、Kimi K3 架构一览

KDA 和 Gated MLA 合起来构成了 Kimi K3 架构三条轴里"序列维度"的改进——Hybrid Attention。论文把整体架构改进归纳为三条轴:序列长度(Hybrid Attention)、网络深度(Attention Residuals)、模型宽度(Stable LatentMoE):

  • Attention Residuals(AttnRes):让每一层可以跨层选择性读取更早层的表示,而不是只接收上一层输出,是深度维度上的信息流扩展。K3 用 Block AttnRes(8 个 block,每 block 12 层)把开销从 O(Ld)O(Ld) 降到 O(Nd)O(Nd)
  • Stable LatentMoE:896 个路由专家中每 token 激活 16 个 + 2 个共享专家。为了稳定极端稀疏下的训练,加入了 RMSNorm、自研的 SiTU-GLU 激活(给 SwiGLU 的两个分支都加上平滑软上限,防止低精度溢出)、以及 Quantile Balancing(直接从路由得分分位数反推负载均衡偏置,替代传统的固定步长符号更新)。
  • MoonViT-V2:与上一代不同,这次视觉编码器完全从零训练(用 next-token prediction 而非对比学习初始化),训练更稳定,且效果与 SigLIP 初始化基线打平。
  • Per-Head Muon:把 Muon 优化器的正交化从全矩阵改成逐 head 独立正交化,避免大幅度 head 主导更新方向。

AttnRes 和 Stable LatentMoE 的完整数学细节,包括 Block AttnRes 的具体接入点、SiTU-GLU 的软天花板设计、Quantile Balancing 的分位数求解,见续篇 《从残差到分位数平衡:拆解 Kimi K3 的 AttnRes 与 Stable LatentMoE》

十一、评测与成本定位速览

第三方评测(2026-07-23 口径):Artificial Analysis Intelligence Index v4.1 为 57.1,580 个模型中排第 4(落后 Claude Fable 5 的 59.9、GPT-5.6 Sol 的 58.9);WebDev Arena 以 1678 Elo 排名第一,超过 Claude Fable 5 的 1634,是首个登顶该榜的开源模型;Text Arena 排第 8/200,Agent Arena 排第 4/37。

成本效率方面,BrowseComp 上以 $2.03/task 拿到最佳分数 91.2%,约为 GPT-5.6 Sol 一半成本;Kimi Code Bench 2.0 上以 Claude Fable 5 38% 的成本落后其 4 分。整体在多个成本-效果对比图上位于或接近前沿。

需要留意的是,"16 个激活专家"不含 2 个每 token 必跑的共享专家;定价、上下文可用性等在官方渠道和第三方 / 媒体报道之间存在差异,引用时最好标明出处。

十二、小结

Kimi K3 的 Hybrid Attention 可以概括成两条互补的设计脉络。KDA 这条线:用一个固定大小的状态矩阵替代无限增长的 KV cache(线性注意力)→ 给状态加上逐通道遗忘(GLA 血统)→ 把直接叠加换成纠错式写入(DeltaNet 血统)→ 用下界衰减和全秩门解决数值稳定性和表达能力问题 → 用 chunkwise 三角求解把串行递推重写成矩阵乘法 → 用 tile 级分层进一步压缩真正的串行深度,换来的是效率,代价是检索变成有损近似。Gated MLA 这条线:把 KV 压缩进低维 latent 而不是丢弃信息,保留精确的全局 O(n2)O(n^2) 检索 → 借助 KDA 已经隐式编码的位置信息,省掉显式位置编码(NoPE)→ 加一层全秩输出门,让每个 token 自己决定读多少全局信息,每 3 层 KDA 后插 1 层,定期给近似检索"校正"一次。每一步改动背后都有明确的动机——不是堆叠概念,而是针对具体的数值问题或硬件效率问题给出的解法。理解了这条脉络,再去看 Attention Residuals、Stable LatentMoE 这些同样服务于"扩展信息流"的模块(见续篇),会更容易抓住它们各自解决的具体问题。

参考资料

  • Kimi Team. Kimi K3: Open Frontier Intelligence. arXiv:2607.24653
  • MoonshotAI/Kimi-K3 — 模型卡与权重
  • José David Baena. Inside Kimi K3: How KDA, AttnRes, and 896 Experts Work
  • Katharopoulos et al. Transformers are RNNs: Fast Autoregressive Transformers with Linear Attention. 2020
  • Yang et al. Parallelizing Linear Transformers with the Delta Rule over Sequence Length(DeltaNet chunkwise 算法)
  • DeepSeek-AI. DeepSeek-V2: A Strong, Economical, and Efficient Mixture-of-Experts Language Model — Multi-head Latent Attention (MLA) 的提出