从线性注意力到 KDA:拆解 Kimi K3 的核心注意力机制
从线性注意力到 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)因果注意力的核心公式是:
问题出在相似度函数 上:指数函数把 和 "缠"在了一起,没办法写成 这种"各算各的,最后再乘起来"的可分解形式。正因为拆不开,每个 都必须和所有 挨个算一遍相似度——这是 复杂度的来源,也是为什么必须把每个历史 token 的 存下来,也就是随长度线性增长的 KV cache。
三、线性注意力的推导:把 softmax 换成可分解核
Linear Attention(Katharopoulos et al., 2020,论文标题就是《Transformers are RNNs》)的思路是换一个能写成两个独立特征映射内积的相似度函数:
这样一换, 就能被合法地搬到求和符号外面:
是一个 的矩阵,累积了"历史 key-value 外积之和",并且可以写成递推形式:
这正是"线性注意力"名字的来源:① 相似度函数可分解(不是指数核);② 因为可分解,整套计算能重写成一个逐步累加的线性递推,复杂度从 降到 ,状态大小固定,不随序列长度增长。这个递推形式在数学上等价于 RNN 的隐状态更新——这也是"Transformers are RNNs"这个标题的含义。
一个最小例子:假设 ,历史 ,,当前 query , 取恒等映射。
标准做法:
线性注意力做法:先算 (与 无关,可提前维护),再算 。结果一样,但状态 可以被复用——这就是效率提升的来源。
四、朴素线性注意力的缺陷,以及到 KDA 的演化线
有个明显缺陷:只会加,从不减。历史 token 无论多久之前都以同等权重永久留在状态里,模型无法学会"这条信息不重要,可以淡出",长序列下新旧信息互相稀释,效果通常明显不如 softmax attention。这条缺陷催生了一整条"如何给线性注意力加遗忘机制"的研究线,最终汇聚到了 KDA。
| 方法 | 状态更新公式 | 遗忘机制 | 写入方式 |
|---|---|---|---|
| 标准 Attention | 无固定状态,存全部 KV | 靠 softmax 权重隐式实现 | — |
| 朴素 Linear Attention | 无 | 直接累加 | |
| RetNet | 全局固定衰减率 | 直接累加 | |
| GLA | 逐通道、输入相关 | 直接累加 | |
| DeltaNet | 无衰减 | 纠错式(先减冲突项再写) | |
| KDA | 逐通道、输入相关 | 纠错式 |

从这张表可以看出,KDA 本质上是把 GLA 的"逐通道遗忘"和 DeltaNet 的"纠错式写入"这两条独立发展的思路合并到一起,再叠加若干工程改造。也正因为血统来自 DeltaNet,它才叫 “Delta Attention”。
五、KDA 完整数学结构
5.1 Delta Rule:用"纠错"取代"叠加"
DeltaNet 的思路借用了经典的 Widrow-Hoff Delta Rule。写入新的 之前,先问一句:如果现在拿 去查现有的表 ,能查出什么?
只把这个误差写进表里,写入强度由 控制:
整理后:
是"把误差写进去", 是"旧表在这个方向上先被清掉一部分,避免新写入和旧记忆打架"。这比朴素线性注意力的无脑叠加稳定得多。
5.2 加上逐通道遗忘门
Delta rule 本身没有主动遗忘机制。KDA 在写入前,对旧状态先做一次逐通道衰减:
是一个向量,对状态的每个通道单独乘一个衰减系数——类似 LSTM 遗忘门,但是逐通道、输入相关,模型可以让"语法结构"这类需要记很久的信息衰减得慢,让临时信息衰减得快。整个更新可以概括为四步:① 旧记忆按通道各自淡忘一点;② 检查新 key 是否与已有记忆冲突,冲突部分先抹掉;③ 写入新的 key-value 关联;④ 用 query 查表得到输出。
5.3 参数是怎么算出来的
先经过局部短卷积(ShortConv)→ Swish 激活 → L2 归一化(归一化让 成为单位向量, 因此是一个几何意义清晰的投影矩阵); 同样过短卷积 + Swish,但不归一化,以保留数值大小信息。 由一个线性层接 Sigmoid 得到, 由一个低秩投影 + 逐头 bias 算出衰减 logit 后再映射得到。
5.4 下界衰减:一个纯工程动机的数学改动
如果 的映射没有下界(上一代 Kimi Linear 用 negative-softplus, 理论上可无限趋近 0),chunkwise 并行算法(第七节)里会用到"累积衰减的倒数" 。当很多个小于 1 的 连乘趋近 0 时,倒数会趋向无穷大,在 BF16 下直接数值溢出。
Kimi K3 把衰减映射换成缩放 Sigmoid,把 限制在固定下界 以内:
倒数因此永远不超过 量级,落在 BF16 安全范围内,使所有 tile(包括后面会讲的对角 tile)都能走密集 Tensor Core 矩乘。这是一个典型的"数学表达式为硬件效率让步"的设计。
5.5 输出门
读出结果 还要过一个输入相关的全秩门才输出:
门的开合程度由当前输入 决定,逐通道控制"这次从记忆里查出的信息要放多少进最终输出"。
六、KDA 的结构图
先看 KDA 在整个 Block 里的位置:Kimi K3 每个 Block 由 3 层 KDA + 1 层 Gated MLA 组成,反复堆叠 23 次,最后再补 1 层 MLA。

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

图中左侧四条竖线是四个并行的参数生成分支(),中间的状态更新链是递归的核心——必须等前一个 token 算完 才能继续,这也是为什么需要专门设计 chunkwise kernel 来加速它。虚线箭头()表示状态矩阵原封不动地带到下一个 token,大小永远不变,这正是 KDA 相对于普通 KV cache 注意力最大的不同点。
七、Chunkwise 并行:把串行递推重写成矩阵乘法
上面的递推是逐 token 串行的,在 GPU 上效率很低——GPU 偏好大矩阵乘法,不喜欢一步一步的小计算。论文给出的解法是把序列切成 chunk(设 chunk size 为 ),chunk 内尽量用矩阵乘法并行,chunk 间才通过状态串行传递。推导分三步递进。
7.1 无衰减、无纠错(热身)
递推 展开后 ,代入 ,写成矩阵形式( 是把 按行堆叠成的 矩阵):
chunk 内的部分其实就是一次普通的带因果 mask 的矩阵乘法,这正是线性注意力能"变回"矩阵乘法的关键。
7.2 加上逐通道衰减
定义累积衰减 ,展开可得 。把衰减挪到 身上分别做缩放:
剩下就是普通点积,。这也是第五节要专门做"下界衰减"的原因—— 出现在分母里,必须保证它不会数值溢出。
7.3 加上 delta 纠错项(真正的难点)
完整递推 没法像前两步一样简单展开,因为 直接作用在 上,而 本身包含之前所有 token 的纠错历史。
猜测最终解具有类似结构:,其中 是"修正后的 value"。代入递推并比较系数,可得:
这个式子对 是线性的,系数 可以用一次矩阵乘 全部提前算出来,于是"求所有 "等价于解一个三角线性方程组。令 ,:
是对角线全 1 的下三角矩阵,保证可逆,且能用前向替换 / 分块递归并行求解。利用方程的线性性,把 的依赖单独剥离:
这正是论文中"UT transform 产出 和 "—— 完全不依赖 ,只用到本 chunk 内的 ,可以对所有 chunk 提前并行算好,不必等前一个 chunk 算完。算好之后只需一步矩阵减法把 接回来。最终套用第一步的框架:
(叠加第二步的衰减重标度后,就是论文公式里完整的 。)
7.4 手算验证
取 ,标量情形,忽略衰减,:;。
逐步递推:;。
三角求解:,,,解得 ,,。两种算法结果一致。
7.5 为什么这样改写更快
| 逐 token 串行算法 | Chunkwise 矩阵算法 | |
|---|---|---|
| 串行步数 | (每个 token 一步) | (每个 chunk 一步, 通常几十到上百) |
| 每一步操作对象 | 整个状态矩阵 (如 128×128) | 三角方程组(如 64×64),远小于状态矩阵 |
| 主要计算形式 | 无法用矩阵乘法表达 | 全是 GEMM + 一次三角求解,都是 GPU 强项 |
真正必须串行的部分被压缩到解一个很小的三角方程组,剩下所有大矩阵运算都变成可以一次性铺开的并行矩阵乘法。chunk 之间仍需把 传给下一个 chunk 作为 ,但这层递归已经从"每个 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 已解出的 值,做一次稠密矩阵乘法,这是 Tensor Core 最擅长的运算,几乎不构成瓶颈。
对照来看,"序列 → chunk"和"chunk → tile"用的是完全相同的模式:内部(对角)做小规模直接计算,之间(非对角)用固定大小的状态或矩阵乘法传递。这种"用小状态串联、中间全用矩阵乘法覆盖"的思路本质上是递归自相似的,理论上可以一直切下去(对应数值线性代数里的分块前向替换,或者线性递推的并行前缀扫描,深度可以降到 )。但工程上在 16 token 这个粒度就停下来,是因为每多切一层都要多一次调度开销,而 16 个 token 的直接计算已经足够便宜——继续细分收益有限,实现复杂度却会上升,最终是数学并行度与工程简单度之间的一个实用平衡点。
九、Gated MLA:KDA 之外的全局交互层
KDA 解决了"序列方向怎么高效检索历史 token",但它把整段历史压进一个固定大小的状态矩阵,本质上是有损压缩——写入越多,早期精确信息被冲刷、被近似的风险就越大。Kimi K3 的 Hybrid Attention 因此没有把 KDA 用到底,而是每 3 层 KDA 后插 1 层 Gated MLA,靠它保留一条**无损、全局、**的精确检索通路。理解 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 向量:
只缓存这个低维的 ,不缓存每个 head 各自的完整 ;真正做 attention 时,再用学到的 up-projection 矩阵从 里重建出各 head 的 content key 和 value。缓存体积因此大幅缩小,但依然是对全部历史 token 做完整的 softmax attention——检索仍然是精确的、无损的,牺牲的只是缓存的存储形式,不是信息本身。

这正是"KDA + MLA 混合"里两者分工的关键:KDA 用固定状态换来 的效率,但检索是近似的;MLA 保留 的精确全局检索,只在缓存形式上做压缩。周期性插入 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 本身是一个依赖顺序的循环过程:状态 的更新天然携带"这是第几步""衰减了多少"这类位置和时效信息,这些信息在 KDA 层处理完之后,已经隐式编码进了送往下一层的隐藏表示里。等这份表示流转到 MLA 层时,位置信息已经"自带"在内容里了,MLA 不需要再单独注入一份显式的位置编码——它只管做基于内容的全局检索,位置感知的活儿完全交给旁边的 KDA 层。
这个设计带来一个实际的工程好处:因为 MLA 层压根没有显式的位置编码参数,扩展上下文长度时不需要重调 RoPE 的频率基数,也不需要套用 YaRN 之类的插值方案——没有这类参数,自然没有"参数要不要重调"的问题。
9.3 Gated:让每个 token 自己决定读多少全局信息
"Gated MLA"的 Gated 前缀,说的是 K3 在 MLA 原始输出之外,又加了一层输入相关、逐通道、全秩的输出门:
是没加门控之前 MLA 的原始输出, 是一个全秩的门投影矩阵——跟 KDA 输出门用的是同一套参数化方式(KDA 一节的输出门 ,两者结构几乎一模一样,只是 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 层)把开销从 降到 。
- 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 而不是丢弃信息,保留精确的全局 检索 → 借助 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) 的提出




