MOE负载均衡问题
为什么需要 MoE
同样的总参数量,MoE 每次推理只激活其中一部分参数——用更少的计算量撬动更大的模型容量。
| 方案 | 总参数 | 每次推理激活 | 计算量 | 知识容量 |
|---|---|---|---|---|
| Dense 模型 | 7B | 7B | 基线 | 7B 级别 |
| Dense 模型 | 35B | 35B | 5× | 35B 级别 |
| MoE 模型 | 35B (含多专家) | ~3.6B | ~0.5× | 35B 级别 |
核心:MoE 把"参数规模"和"计算量"解耦了。35B 总参、只激活 3.6B——知识容量向 35B 看齐,推理成本向 7B 看齐。这就是 Qwen3.6-35B-A3B 名字的含义:35B 总参,3B 活跃参数。
MoE 核心架构
两个核心组件
1、路由器(Router / Gate)
一个轻量的线性层,输入每个 token 的 hidden state,输出每个专家的"适配分数"。Top-K 选择分数最高的 K 个专家。
s = Wr · h → TopK(s, k=2)
2、专家(Expert)
每个专家是一个独立的前馈网络(FFN),通常是标准 Transformer 中 FFN 的副本。不同专家在训练中自然分化,各自擅长不同类型的输入模式。
标准 MoE 层的计算流程
# 标准 Top-K MoE:Token 选专家
h = input_hidden # shape: (n_tokens, d_model)
# Step 1: 路由打分
logits = router(h) # (n_tokens, n_experts)
# Step 2: Top-K 选择
scores, indices = topk(logits, k=2) # 每个 token 选 2 个专家
weights = softmax(scores) # 对选中的专家分数做 softmax
# Step 3: 各专家并行计算
output = 0
for expert_id in range(n_experts):
mask = (indices == expert_id) # 哪些 token 分配给了这个专家
if mask.any():
expert_out = expert[expert_id](h[mask])
output[mask] += weights[mask] * expert_out
return output
MoE 层在 Transformer 中的位置
Multi-Head Attention → Add & Norm → MoE FFN Layer → Add & Norm
↑
Attention 权重是共享的
只有 FFN 被替换成了 MoE
MoE 只替换 Transformer 中的 FFN 层,Attention 层保持不变。一个典型的 MoE Transformer 可能每隔一层才放 MoE(比如 Mixtral 的做法),或者每层都放(比如 DeepSeek-V2/V3)。
核心缺陷:负载不均衡
什么是负载不均衡
在标准 Top-K 路由中,每个 token 自己选择专家。训练过程中,路由器可能学会"偷懒"——把大量 token 分配给少数几个专家,而其他专家几乎闲置:
// 8 个专家,某一步的 token 分配情况(batch=64 tokens)
专家0: ████████████████████████████ 31 tokens ← 过载!
专家1: ██████████ 10 tokens
专家2: ████████ 8 tokens
专家3: ████ 4 tokens
专家4: ███ 3 tokens
专家5: ██ 2 tokens
专家6: █ 1 token ← 几乎闲置
专家7: 0 tokens ← 完全闲置!
不均衡带来的后果
后果一:计算效率崩塌
MoE 的并行策略是每个专家跑一块 GPU(Expert Parallelism)。如果专家0 有 31 个 token 而专家7 有 0 个,那么 GPU0 忙死、GPU7 闲死——其他 GPU 必须等 GPU0 算完才能进行下一步。负载最重的专家决定了整个 batch 的延迟。
31 tokens 的专家决定了所有人的等待时间 → 实际并行效率可能不到 50%。
后果二:训练不充分
被冷落的专家(4-7)每步只看到极少的 token,梯度更新不充分——它们永远追不上热门专家。这在训练早期尤其严重——一旦某几个专家"抢跑",整个路由就固化了。
后果三:Token 丢弃
实际部署中,每个专家有容量上限(expert capacity),超出的 token 直接丢弃——这些 token 的信息在这一层完全丢失。容量公式通常是:
capacity_factor 通常设为 1.25~1.5,意味着允许 25%~50% 的溢出缓冲。但如果某些专家严重过载,缓冲也不够用,token 就被强制丢弃了。
为什么会不均衡——路由坍塌
根源在于路由器的正反馈循环:
Step 1: 初始化时路由器随机分配 → 略有偏差
↓
Step 2: 热门专家看到更多 token → 梯度更新更充分 → 输出质量更高
↓
Step 3: 路由器学会"热门专家=好输出" → 分配更多 token 给它们
↓
Step 4: 冷门专家 token 更少 → 梯度更稀疏 → 差距继续拉大 → GOTO Step 2
这就是所谓的"富者愈富"效应(rich-get-richer):路由坍塌一旦开始,很难靠模型自己恢复。必须从架构层面介入。
解法一:细粒度专家(Fine-Grained Experts)
核心思想:把一个大专家切成多个小专家 → 每个专家处理能力更小 → 负载更分散
传统的"粗粒度"专家
标准 MoE 中,每个专家就是一个完整的 FFN 层。以 7B 模型为例:
# 粗粒度:8 个专家,每个专家 = 完整 FFN(~110M 参数)
n_experts = 8, expert_size = 110M
总 MoE 参数 = 8 × 110M = 880M(仅 FFN 部分)
细粒度的做法
DeepSeek-V2 提出:把 FFN 内部再切分,让专家的粒度更细:
# 细粒度:64 个专家,每个专家 = FFN 的 1/8
n_experts = 64, expert_size = 13.75M
总 MoE 参数 = 64 × 13.75M = 880M(总参不变!)
| 粗粒度 | 细粒度 | |
|---|---|---|
| 专家数量 | 8 | 64 |
| 每个专家大小 | 110M | 13.75M |
| 总参数 | 880M | 880M |
| 每个专家处理能力 | 强(完整 FFN) | 弱(1/8 FFN) |
| 负载分布 | 容易集中 | 自然分散 |
为什么细粒度能缓解不均衡
原因一:容量上限自然降低
专家变小了,每个专家的处理上限也随之降低。即使某些专家被分配了更多 token,因为本身"胃口小",很快就会达到容量上限,溢出的 token 会被分配给其他专家。这就像自助餐换成了小盘子——每个人拿的少了,排队自然均衡。
原因二:激活更多专家
细粒度下通常 Top-K 也相应增大(比如 k=8 而不是 k=2)。每个 token 看到更多专家,路由决策的"容错率"更高——即使 router 把某个 token 分配给了一个"不太合适"的专家,还有 7 个其他专家兜底。
原因三:专家专业化更灵活
小专家更容易学到细粒度的专长。比如"法律合同条款"可以由专家12+专家28+专家45 组合处理,而不是一个巨大的"法律专家"把所有法律相关 token 全吃掉。
细粒度 + 共享专家(DeepSeek-V2/V3 的实际方案)
DeepSeek 还引入了一个关键设计:共享专家(Shared Expert)。所有 token 都会经过共享专家,而路由专家只负责"增量":
# DeepSeekMoE 架构
h = input_hidden
# 共享专家:所有 token 都经过
shared_out = SharedExpert(h)
# 路由专家:细粒度 + Top-K,每个 token 选 k 个小专家
routed_out = MoE_Router(h, topk=6, n_experts=64)
# 最终输出 = 共享 + 路由
output = shared_out + routed_out
共享专家的妙处:它保证了每个 token 都有"底线能力"(常识、基础语言能力),路由专家只负责"特长"。这样即使路由完全失败,共享专家也能保证输出不崩溃——这是一个非常重要的鲁棒性设计。
解法二:专家选Token(Expert-Choice Routing)
核心思想:反过来——不是 token 选专家,而是专家选 token。每个专家主动挑选自己最擅长处理的 K 个 token。
Token-Choice vs Expert-Choice
| Token-Choice(标准) | Expert-Choice(反转) | |
|---|---|---|
| 谁做选择 | 每个 token 选 top-k 专家 | 每个专家选 top-k token |
| 路由计算 | softmax(router(h)) per token | softmax(router(h)) per expert |
| 负载保证 | 不保证——可能全部 token 选同一个专家 | 天然均衡——每个专家固定处理 k 个 token |
| token 覆盖 | 每个 token 一定被处理 | 部分 token 可能无人选择 |
专家选Token 的计算流程
# Expert-Choice Routing
h = input_hidden # (n_tokens, d_model)
# Step 1: 计算所有 token 对所有专家的适配分数
scores = router(h) # (n_tokens, n_experts)
# Step 2: 对每个专家维度做 softmax(注意:和 Token-Choice 相反!)
scores = softmax(scores, dim=0) # 沿 expert 维度归一化 → 每个专家对 token 的偏好
# Step 3: 每个专家选 top-k 个 token
for expert_id in range(n_experts):
top_tokens = topk(scores[:, expert_id], k=capacity)
# expert_id 处理这 k 个 token
关键区别:softmax 的方向变了。Token-Choice 是每个 token 在自己这行做 softmax(选专家),Expert-Choice 是每个专家在自己这列做 softmax(选 token)。这个看似微小的变化,彻底改变了负载特性。
为什么能天然均衡
每个专家固定处理 K 个 token → 绝对均衡
在 Expert-Choice 中,每个专家的 token 数 = capacity = K。这不再是"希望"均衡,而是架构上强制均衡——无论路由器学成什么样,负载一定是均衡的。
# Expert-Choice 下,负载天然均衡
专家0: ████████ 8 tokens
专家1: ████████ 8 tokens
专家2: ████████ 8 tokens
专家3: ████████ 8 tokens
专家4: ████████ 8 tokens
专家5: ████████ 8 tokens
专家6: ████████ 8 tokens
专家7: ████████ 8 tokens
# 完美均衡!但注意:total = 64 tokens,不是所有 token 都覆盖了
# 如果有 100 个 token,那 36 个没人选——这就是 Expert-Choice 的代价
两种解法的局限性
细粒度专家的局限
局限一:通信开销激增
细粒度意味着更多专家(64→128→256)。在分布式训练中,不同专家分布在不同 GPU 上。每个 token 需要和更多专家通信——All-to-All 通信量随专家数线性增长。当专家数超过某个阈值(比如 256),通信开销会吃掉所有加速收益。
局限二:缓解不等于解决
细粒度只是让不均衡"没那么严重",并不能消除。Top-K 路由器依然存在——k 可以调大、专家可以切小,但路由坍塌的本质没有变:路由器仍然可以学会把所有 token 分配给某几个专家。细粒度是治标:让溢出的影响更小,但根因还在。
局限三:辅助损失(Load-Balancing Loss)的副作用
细粒度方案通常需要配合负载均衡损失(Load-Balancing Loss)——在训练 loss 中加一项,惩罚负载偏差。但这引入了一个新问题:
α 太大 → 路由过于"平均主义",专家学不到专长。α 太小 → 不均衡依然严重。α 是一个需要精细调参的超参,不存在普适的最优值。
局限四:专家总数有上限
细粒度不能无限切——每个专家至少要保持一定容量才能学到有意义的模式。DeepSeek-V2 用的是 64 个路由专家 + 2 个共享专家,已经是实践中比较激进的设置了。如果再切到 256 个,单个专家太小,反而学不到有效的特征变换。
专家选Token 的局限
局限一:Token 丢弃——最大的硬伤
这是 Expert-Choice 最致命的问题。每个专家只选 top-K 个 token,那么:
被丢弃的 token 在这一层完全不做任何处理——相当于信息直接丢失。在深层网络中,信息丢失会逐层放大,严重影响模型质量。
局限二:"你情我不愿"——质量 vs 均衡的矛盾
Token-Choice 的问题:token 选了专家,但专家可能"不擅长"这个 token(负载不均衡)。Expert-Choice 解决了负载问题,但引入了相反的质量问题:为了填满容量,专家不得不选一些自己并不擅长的 token。
# 专家 0 最擅长数学类 token,但 batch 里只有 3 个数学 token
# Expert-Choice 强制专家 0 选 k=8 个 token
# → 另外 5 个 token 属于"赶鸭子上架"
专家0 擅长: [数学] [数学] [数学] ✓
专家0 被迫: [文学] [代码] [历史] [生物] [地理] ← 质量下降
局限三:推理时的动态性困境
Expert-Choice 需要看到整个 batch 的所有 token才能决定每个专家选哪些——因为 softmax 在 token 维度上计算,必须有全局视野。这在推理时尤其麻烦:
- 自回归生成时,token 是一个一个来的,没有"整个 batch"可选
- 要么等攒够一批再处理(增加延迟),要么退化为 Token-Choice
- DeepSeek-V3 在推理时就退回了 Token-Choice + 辅助损失的方式
局限四:Top-K 选择的梯度断裂
Top-K 选择本身是不可导的——选中的 token 有梯度,没选中的没有。在 Expert-Choice 中,大量 token 可能长期不被任何专家选中,这些 token 的梯度信号完全中断。模型的训练效率取决于"token-专家的匹配质量",而这个质量本身又需要充分训练才能获得——先有鸡还是先有蛋。
三种路由方案对比
| 维度 | Token-Choice (传统 Top-K) | 细粒度 + Token-Choice (DeepSeek-V2) | Expert-Choice (反转路由) |
|---|---|---|---|
| 选择方向 | Token → 专家 | Token → 专家 | 专家 → Token |
| 负载均衡 | 差,容易坍塌 | 中等,靠辅助损失 | 天然均衡 |
| Token 覆盖率 | 100% | 100% | 取决于 n_experts × K |
| 推理适用性 | 好 | 好 | 差(需攒 batch) |
| 通信开销 | 低 | 中高 | 低 |
| 训练稳定性 | 差 | 中等 | 中等 |
| 代表模型 | Mixtral 8×7B Switch Transformer |
DeepSeek-V2/V3 Qwen3-MoE |
Google Sparsely-Gated (论文方案,未大规模采用) |
业界最终选择:DeepSeek-V2/V3 的方案——细粒度 + 共享专家 + 辅助损失 + 训练时用 细粒度Token-Choice + 推理时退回简单路由——是目前 MoE 领域被验证最成功、最实用的路径。Expert-Choice 在理论上很优雅(天然均衡),但 token 丢弃问题在工程上难以接受。这也是为什么它至今没有被任何大规模生产模型采用。
常见问题汇总
总结:
MoE 是当前扩大模型规模最具性价比的路线——DeepSeek-V3 671B 总参只激活 37B,训练成本约为同规模 Dense 模型的 1/5。但负载不均衡仍然是核心瓶颈。未来方向可能在动态路由(不是固定的 Top-K,而是根据输入复杂度动态决定激活多少专家)、硬件级稀疏计算支持(GPU/NPU 对稀疏专家计算的 native 支持)、以及MoE + 蒸馏(训大 MoE,蒸馏到小 Dense 部署)。
参考文献
| # | 论文 | 核心贡献 |
|---|---|---|
| 1 | Outrageously Large Neural Networks: The Sparsely-Gated Mixture-of-Experts Layer Shazeer et al., Google Brain, 2017 |
首次将 MoE 引入深度神经网络,提出 Sparsely-Gated 路由、Top-K 选择 + 辅助负载均衡损失,奠定整个领域基础。 |
| 2 | GShard: Scaling Giant Models with Conditional Computation and Automatic Sharding Lepikhin et al., Google, 2020 |
将 MoE 扩展到 600B 参数,提出 Expert Parallelism + All-to-All 通信,验证了 MoE 在大规模下的工程可行性。 |
| 3 | Switch Transformers: Scaling to Trillion Parameter Models with Simple and Efficient Sparsity Fedus et al., Google, 2021 |
Top-1 路由 + 可微分 Load-Balancing Loss。首次系统对比 Token-Choice 与 Expert-Choice 两种路由策略(§3.2),指出 Expert-Choice 天然均衡但导致 token 丢弃。 |
| 4 | MegaBlocks: Efficient Sparse Training with Mixture-of-Experts Gale et al., Stanford & Google, 2022 |
提出 block-sparse 计算方案,量化分析了 Expert-Choice 路由的 token 丢弃问题,指出这是其难以大规模部署的核心瓶颈。 |
| 5 | DeepSeek-V2: A Strong, Economical, and Efficient Mixture-of-Experts Language Model DeepSeek-AI, 2024 |
细粒度专家里程碑。细粒度专家切分 + 共享专家隔离 + 负载均衡策略。236B 总参、21B 激活,训练成本仅为 Dense 的 1/3。 |
| 6 | DeepSeek-V3 Technical Report DeepSeek-AI, 2024 |
Auxiliary-Loss-Free 负载均衡。通过动态调整 expert bias 实现均衡,完全消除辅助损失。671B 总参、37B 激活。 |

浙公网安备 33010602011771号