<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>MoE on 辰远</title>
        <link>/tags/moe/</link>
        <description>Recent content in MoE on 辰远</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <copyright>Lee</copyright>
        <lastBuildDate>Wed, 23 Sep 2026 18:57:28 +0800</lastBuildDate><atom:link href="/tags/moe/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>DeepSeek-V2/V3：大模型的两张账，为什么 MLA 与 MoE 要一起看</title>
            <link>/p/deepseek-mla-moe/</link>
            <pubDate>Wed, 23 Sep 2026 00:00:00 +0000</pubDate>
            <guid>/p/deepseek-mla-moe/</guid>
            <description>&lt;img src=&#34;/p/deepseek-mla-moe/cover.jpg&#34; alt=&#34;Featured image of post DeepSeek-V2/V3：大模型的两张账，为什么 MLA 与 MoE 要一起看&#34; /&gt;&lt;p&gt;把一个模型写成“671B 参数”，很容易让人以为每生成一个 token 都要搬动、计算全部 671B 参数；把上下文窗口写成“128K”，也容易让人只想到注意力的计算量。DeepSeek-V2/V3 真正有解释价值的地方，是把这两种成本拆成了两张不同的账：&lt;strong&gt;每个 token 需要保留多少历史状态，以及每个 token 需要激活多少模型参数。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Multi-head Latent Attention（MLA）处理第一张账。它不为每个注意力头保存完整的 key 和 value，而是保存一个可恢复它们的低维联合潜变量。DeepSeekMoE 处理第二张账。模型可以拥有大量专家参数，但路由器只让当前 token 经过少数专家。两者共同指向一个系统原则：模型的总容量、单 token 计算量和在线服务内存，不必按同一比例增长。&lt;/p&gt;&#xA;&lt;p&gt;这比“又一个更大的模型”重要。DeepSeek-V2 论文报告，相比 DeepSeek 67B，它把 KV cache 减少 93.3%，最大生成吞吐提升到 5.76 倍，同时以 236B 总参数、21B 激活参数支持 128K 上下文。V3 沿用 MLA 与 DeepSeekMoE，把规模扩到 671B 总参数、每 token 约 37B 激活参数。数字来自各自技术报告，不能脱离其硬件、精度和服务设置横向外推；但它们清楚证明，这套架构不是只在小模型消融中成立。&lt;/p&gt;&#xA;&lt;h2 id=&#34;第一张账生成时显存主要记住了什么&#34;&gt;第一张账：生成时，显存主要记住了什么&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;自回归生成一次只新增一个 token。为了避免每一步重新计算整个前缀，Transformer 会把先前 token 的 key 和 value 留在 KV cache 中。标准多头注意力（MHA）在每一层、每个 token 上需要缓存的元素数是：&lt;/p&gt;&#xA;$$2n_h d_h$$&lt;p&gt;其中 $n_h$ 是注意力头数，$d_h$ 是每个头的维度，前面的 2 分别对应 K 与 V。把层数、序列长度、batch size 和元素字节数乘进来，缓存会随并发与上下文长度线性增长。解码阶段每一步都要读取这段不断变长的历史，因此瓶颈经常不是矩阵乘法峰值，而是显存容量与带宽。&lt;/p&gt;&#xA;&lt;p&gt;MQA 让所有 query head 共享一组 K/V，GQA 让若干 query head 共享一组 K/V，都能缩小缓存；代价是不同 query head 可使用的历史表示也被共享。DeepSeek-V2 的问题不是“怎样少设几个 KV head”，而是更激进的一步：&lt;strong&gt;是否根本不必缓存展开后的 K/V？&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;figure&gt;&lt;img src=&#34;/p/deepseek-mla-moe/mla-cache.svg&#34;&gt;&lt;figcaption&gt;&#xA;&#x9;&#x9;&#x9;&lt;h4&gt;图 1：MHA 缓存每个头的完整 K/V；MLA 只缓存 K/V 联合潜变量和独立的位置键&lt;/h4&gt;&#xA;&#x9;&#x9;&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;p&gt;MLA 先把当前隐藏状态 $h_t$ 下投影成一个低维潜变量：&lt;/p&gt;&#xA;$$c_t^{KV}=W^{DKV}h_t$$&lt;p&gt;再由两组上投影恢复内容 key 与 value：&lt;/p&gt;&#xA;$$k_t^C=W^{UK}c_t^{KV},\qquad v_t^C=W^{UV}c_t^{KV}$$&lt;p&gt;训练时网络仍然可以为不同注意力头形成不同的 K/V；生成时真正留下的却只是 $c_t^{KV}$。关键不只是“低秩”两个字，而是 K 与 V &lt;strong&gt;联合&lt;/strong&gt;压缩：同一个潜变量服务两者，缓存维度 $d_c$ 远小于把所有头的 K/V 展开后的 $2n_hd_h$。&lt;/p&gt;&#xA;&lt;p&gt;更巧的一步发生在计算图上。$W^{UK}$ 可以预先吸收到 query 投影中，$W^{UV}$ 可以吸收到输出投影中。这样注意力分数可以直接用变换后的 query 与缓存潜变量相乘，聚合结果也能在潜空间完成后再映射出去。官方 V3 推理代码把两条路径直接命名为 &lt;code&gt;naive&lt;/code&gt; 与 &lt;code&gt;absorb&lt;/code&gt;：前者显式构造并缓存完整 K/V，后者只缓存归一化后的低秩 KV 和位置分量。这段实现让论文里的代数变换变成了可检查的运行路径。&lt;/p&gt;&#xA;&lt;h2 id=&#34;rope-是压缩链路里那块不能随便移动的石头&#34;&gt;RoPE 是压缩链路里那块不能随便移动的石头&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;如果事情只有线性投影，上述矩阵吸收很直接。RoPE 带来麻烦：它对 query 和 key 做与 token 位置相关的旋转。若先恢复 $k_t^C$，再对它施加 RoPE，那么上投影 $W^{UK}$ 与位置矩阵之间隔着一次不能交换次序的变换。生成第 $t$ 个 token 时，系统无法把 $W^{UK}$ 永久吸收到 query 一侧；最坏情况下还需要为前缀重新得到位置相关的 key，压缩收益就被破坏了。&lt;/p&gt;&#xA;&lt;p&gt;DeepSeek 的解法是把 key/query 分成“内容”和“位置”两条通道。内容部分走低秩压缩并允许矩阵吸收；一个额外的小维度 query/key 分支单独承载 RoPE。每个头拥有自己的位置 query $q_{t,i}^{R}$，但位置 key $k_t^{R}$ 在头之间共享。最终的注意力匹配是两部分拼接后的内积，缓存则只需留下：&lt;/p&gt;&#xA;$$c_t^{KV}\quad\text{和}\quad k_t^R$$&lt;figure&gt;&lt;img src=&#34;/p/deepseek-mla-moe/rope-absorb.svg&#34;&gt;&lt;figcaption&gt;&#xA;&#x9;&#x9;&#x9;&lt;h4&gt;图 2：解耦 RoPE 把位置相关变换移出可吸收的内容投影链路&lt;/h4&gt;&#xA;&#x9;&#x9;&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;p&gt;按 V2 的配置，$d_c=4d_h$，位置维度 $d_h^R=d_h/2$，所以每层每 token 缓存 $(d_c+d_h^R)=4.5d_h$ 个元素。论文把它描述为约等于只有 2.25 组的 GQA，同时在其消融实验中保持与 MHA 相当或更好的模型质量。这里应避免把“低秩”误解为免费压缩：表示空间、训练稳定性和专用 kernel 都要重新设计；MLA 节省的是持续占用和搬运的缓存，未必减少每个阶段的所有计算。&lt;/p&gt;&#xA;&lt;h2 id=&#34;第二张账参数很多不代表每次都要全部计算&#34;&gt;第二张账：参数很多，不代表每次都要全部计算&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;注意力之后，Transformer 的另一大块成本是前馈网络。普通稠密模型的每个 token 都经过同一组 FFN 参数，模型容量与计算量紧密绑定。MoE 把一个 FFN 换成多个专家，再用路由器为 token 选择 Top-K 专家，因此总参数可以快速增加，而每 token 的激活参数增长较慢。&lt;/p&gt;&#xA;&lt;p&gt;DeepSeekMoE 在常规 Top-K MoE 上做了两处有目的的拆分。第一，把大专家切成更多细粒度专家，同时增加被选择的数量。在总激活参数近似不变时，路由器能组合出更丰富的专家子集。第二，隔离一部分共享专家，让所有 token 都经过它们，专门承载普遍知识；其余路由专家便不必各自重复学习同一套基础能力。&lt;/p&gt;&#xA;&lt;figure&gt;&lt;img src=&#34;/p/deepseek-mla-moe/moe-routing.svg&#34;&gt;&lt;figcaption&gt;&#xA;&#x9;&#x9;&#x9;&lt;h4&gt;图 3：共享专家负责公共能力，路由专家以细粒度组合提供专门容量&lt;/h4&gt;&#xA;&#x9;&#x9;&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;p&gt;这解释了“总参数”和“激活参数”为何必须同时写。V2 的 236B/21B、V3 的 671B/37B 不是营销上任选一个更好看的数字：前者近似描述权重中可容纳的知识容量与部署存储，后者更接近一次前向中真正参与计算的参数规模。但激活参数也不是完整延迟公式。专家权重需要被搬到计算单元，token 需要跨设备分发，负载不均会让最忙的设备拖慢整个批次；MoE 把部分算力问题转化成了通信、调度和负载均衡问题。&lt;/p&gt;&#xA;&lt;h2 id=&#34;v3-为什么不再让平衡直接惩罚模型&#34;&gt;V3 为什么不再让“平衡”直接惩罚模型&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;早期 MoE 通常给训练损失加一个辅助项，迫使 token 更均匀地分配给专家。这样能防止少数专家过载，却会把系统目标混入语言建模目标：某个领域本来可能更适合集中使用一组专家，辅助损失却要求单条序列也尽量平均。&lt;/p&gt;&#xA;&lt;p&gt;V3 的主要变化之一，是用专家级偏置 $b_i$ 调整 Top-K 选择。路由仍依据 token 与专家的亲和分数，但用于选择的分数加上动态偏置；某个专家近期过载，偏置就降低，欠载则提高。重要的是，这个偏置影响“选谁”，不直接乘进专家输出，也不把平衡项加到主要训练损失中。论文仍保留了极小的序列级辅助损失以防单序列极端失衡，因此“无辅助损失”更准确地说，是&lt;strong&gt;主要的专家负载均衡不再依赖辅助损失&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;V3 的消融给了一个有分寸的结论：在 15.7B 和 228.7B 两个基线尺度上，这种策略在多数列出的基准上优于纯辅助损失方案；论文进一步比较批次级与序列级平衡，认为较宽松的批次级约束允许不同领域形成更清晰的专家偏好。它并没有证明偏置法在任何硬件、batch 或领域分布下都最好。部署仍需冗余专家和动态调度来应对真实流量的偏斜。&lt;/p&gt;&#xA;&lt;h2 id=&#34;两张账合在一起才是端到端效率&#34;&gt;两张账合在一起，才是端到端效率&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;MLA 与 MoE 经常被分别介绍为两个模块，但它们在服务系统里解决的是相邻瓶颈：MLA 让每个请求的历史状态更小，MoE 让每个新 token 只使用模型容量的一小部分。前者有利于放入更长上下文或更大 batch，后者让总容量扩张时计算量不必同步扩张。只有其中之一，另一张账仍可能成为上限。&lt;/p&gt;&#xA;&lt;p&gt;这也解释了为什么算法公式之后还需要工程实现。MLA 要有能直接消费压缩缓存的 attention kernel；MoE 要有高效 all-to-all、专家并行和负载调度。DeepSeek 后续公开的 FlashMLA 针对 MLA 解码提供专用 kernel，V3 报告则花了相当篇幅讨论通信重叠与跨节点路由。架构减少了理论上必须搬运和激活的量，系统软件决定这些节省能否真正变成吞吐。&lt;/p&gt;&#xA;&lt;p&gt;最值得带走的判断不是“低秩一定胜过 GQA”或“MoE 一定胜过稠密模型”。MLA 需要合适的压缩维度、位置编码拆分和 kernel 支持；MoE 需要足够大的负载、网络与调度能力，低 batch 场景甚至可能付出额外延迟。更可靠的原则是：&lt;strong&gt;不要只问模型有多少参数，也不要只问上下文有多长；要问每个 token 实际缓存什么、读取什么、激活什么，以及这些张量怎样穿过硬件。&lt;/strong&gt; DeepSeek-V2/V3 的贡献，是把这四个问题一起写进了模型架构。&lt;/p&gt;&#xA;&lt;h2 id=&#34;参考资料&#34;&gt;参考资料&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;DeepSeek-AI, &lt;a class=&#34;link&#34; href=&#34;https://arxiv.org/abs/2405.04434&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xD;&#xA;    &gt;DeepSeek-V2: A Strong, Economical, and Efficient Mixture-of-Experts Language Model&lt;/a&gt;, 2024.&lt;/li&gt;&#xA;&lt;li&gt;DeepSeek-AI, &lt;a class=&#34;link&#34; href=&#34;https://arxiv.org/abs/2412.19437&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xD;&#xA;    &gt;DeepSeek-V3 Technical Report&lt;/a&gt;, 2024/2025.&lt;/li&gt;&#xA;&lt;li&gt;Dai et al., &lt;a class=&#34;link&#34; href=&#34;https://arxiv.org/abs/2401.06066&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xD;&#xA;    &gt;DeepSeekMoE: Towards Ultimate Expert Specialization in Mixture-of-Experts Language Models&lt;/a&gt;, 2024.&lt;/li&gt;&#xA;&lt;li&gt;DeepSeek-AI, &lt;a class=&#34;link&#34; href=&#34;https://github.com/deepseek-ai/DeepSeek-V3&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xD;&#xA;    &gt;DeepSeek-V3 official repository and reference inference implementation&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;DeepSeek-AI, &lt;a class=&#34;link&#34; href=&#34;https://github.com/deepseek-ai/DeepSeek-V2&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xD;&#xA;    &gt;DeepSeek-V2 official repository&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;DeepSeek-AI, &lt;a class=&#34;link&#34; href=&#34;https://github.com/deepseek-ai/FlashMLA&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xD;&#xA;    &gt;FlashMLA: Efficient Multi-head Latent Attention Kernels&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
        </item></channel>
</rss>
