AI 技术
#MoE#专家并行#All-to-All#推理优化#负载均衡

MoE 专家并行的 All-to-All 通信瓶颈:专家越多推理延迟为何反而上升

多卡部署稀疏 MoE 时,专家数量增加并不总带来延迟下降。文章以在线推理服务为场景,拆解 token 经 All-to-All 分发与回收的过程,分析跨卡通信量、负载不均和容量因子如何抵消稀疏计算收益,并给出可观测指标与调优边界。

一个反直觉的扩容结果

假设你在一套 8 卡节点上部署一个稀疏 MoE 模型,每个 Transformer 层把前馈网络替换成若干专家,路由器为每个 token 选择 Top-K 个专家。起初专家总数较少,每张卡放几个专家,推理延迟还能接受。为了继续提升模型容量,你把专家数从几十个扩到上百个,每张卡分到的专家更少,单卡计算量看起来更小。但压测结果往往相反:首 token 延迟和每 token 延迟不降反升,GPU 利用率反而下降。

直觉上,专家越多,单个专家处理的 token 越少,计算越稀疏,应该更快。问题出在稀疏计算省下的是矩阵乘时间,而专家并行(Expert Parallelism, EP)引入的跨卡通信并没有随专家数增加而减少,反而因为路由分散、每卡专家变少而变得更频繁、更碎片化。当通信时间超过计算节省的时间,扩容就变成负收益。

下面以一个在线推理服务为贯穿场景:8 张 GPU 组成一个 EP 组,服务一个 Top-2 的 MoE 模型,每层有 E 个专家,专家按卡切分。请求以 batch 形式进入,每层都要做一次“分发—专家计算—回收”。我们关心的是这条路径上到底发生了什么。

基线方案在哪里失效

先看稠密模型的做法。稠密 FFN 的权重在所有卡上按张量并行或流水并行切分,每个 token 都要经过同一组权重,通信模式固定:要么是规整的 all-reduce,要么是规整的 all-gather。通信量只与隐藏维度、batch 大小有关,与“哪个 token 去哪”无关。

MoE 打破了这种规整性。路由器为每个 token 独立选择专家,不同 token 去不同卡,每张卡收到的 token 数量取决于当批数据的路由分布。这就产生三个稠密模型没有的问题:

  • 分发与回收必须按 token 的专家归属重新排列数据,本质是一次 all-to-all。
  • 每个专家收到的 token 数不同,形成 ragged tensor,规整的 GEMM 无法直接套用。
  • 路由是学出来的,训练和推理中分布会偏移,某些专家可能长期过热或过冷。

DeepSpeed-MoE 的论文指出,MoE 模型虽然相比同质量稠密模型有显著训练成本优势,但由于模型规模更大、结构特殊,如何提供快速 MoE 推理仍是未解决的问题,其工作正是针对这一推理瓶颈。NVIDIA 的工程博客也给出一个更直接的观察:在未优化的 DeepSeek-V3 训练基线上,GPU 间通信占累计 kernel 时间的 84%。这虽然是训练场景的数字,但说明在 EP 下通信可以成为主导项。

推理场景的处境类似,甚至更敏感:训练可以用大 batch 摊薄通信,在线推理的 batch 受延迟约束,往往更小,通信占比更高。

All-to-All 分发与回收的机制

要理解延迟为何随专家数上升,必须把每层 MoE 的数据流拆开。设 EP 组有 W 张卡,每卡持有 E/W 个专家。一个 batch 里有 N 个 token,每个 token 被路由到 K 个专家。

分发阶段:每张卡上的 token 先经过本地路由器,得到目标专家编号。由于专家分布在不同卡上,卡 i 需要把发往卡 j 专家的 token 发送过去。这一步通常实现为一次 all-to-all:每张卡既是发送方也是接收方,发送量取决于本卡 token 的目标分布,接收量取决于其他卡 token 落到本卡专家的数量。

专家计算阶段:每张卡收集到属于自己的 token 后,按专家分组做 grouped GEMM。每个专家的 token 数不同,所以这是一组变长矩阵乘。

回收阶段:专家输出需要按原 token 顺序送回发起卡,再做加权合并。这通常是第二次 all-to-all,方向与分发相反。

flowchart TD
    A[各卡本地 token] --> B[路由器选 Top-K 专家]
    B --> C[按目标卡分组打包]
    C --> D[All-to-All 分发]
    D --> E[各卡按专家分组]
    E --> F[Grouped GEMM 专家计算]
    F --> G[按来源卡打包输出]
    G --> H[All-to-All 回收]
    H --> I[加权合并回原 token 顺序]
    I --> J[进入下一层]

关键转折点在 D 和 H:这两次 all-to-all 的通信量不取决于单卡计算量,而取决于 token 的跨卡流动。专家数增加时,每卡持有的专家变少,token 更可能落到别的卡上,跨卡流动比例上升,通信量随之增加。

专家越多,通信为什么越重

把上面的机制量化一下。每个 token 每层要发送 K 份数据(K 个专家各一份),每份大小约为隐藏维度 d 乘以数据类型字节数。若 batch 有 N 个 token,单卡平均发送量约为 N·K·d·b / W(b 为字节数),接收量同量级。这还没算分发时的元数据(token 索引、专家编号、权重)。

专家数 E 增加时,W 不变,每卡专家数 E/W 减少。考虑一个极端:E = W,每卡一个专家,那么几乎所有 token 都要跨卡,跨卡比例接近 1。反之 E 远大于 W 时,每卡持有多个专家,token 有更大概率落在本卡,跨卡比例下降。

所以通信量并不直接由 E 决定,而由“token 落在本卡专家的概率”决定。这个概率取决于路由分布和专家到卡的映射。工程上通常的做法是把专家均匀打散到各卡,让任意 token 落到本卡的概率约为 (E/W)/E = 1/W。但这只是期望值。真实路由分布是偏斜的:少数专家吃掉大量 token,如果这些热门专家恰好集中在某几张卡上,那几张卡就会成为通信和计算的双重热点。

这就解释了反直觉现象的来源:增加 E 本意是让每个专家更专精、单卡计算更轻,但如果映射不当或路由偏斜,跨卡比例和热点集中度都会上升,通信时间吃掉计算节省。

负载不均如何抵消稀疏收益

路由偏斜是 MoE 的固有难题。NVIDIA 博客明确指出,路由器是学出来的,训练过程中分布可能严重偏斜,路由器会对某些专家形成偏好;没有两个 batch 的专家负载相同,同一个 batch 内一个专家收到的 token 可能远多于另一个。

在 EP 推理中,这带来两层损失:

第一层是计算不均衡。每张卡的专家计算时间取决于本卡所有专家收到的 token 总数。如果卡 A 收到 500 个 token、卡 B 只收到 80 个,即使卡 B 早早算完,也必须等卡 A,整个 EP 组的这一步耗时由最慢的卡决定。这就是木桶效应:增加专家数本应降低单卡平均负载,但偏斜让最慢卡负载不降。

第二层是通信不均衡。热门专家所在卡要接收大量 token,其入向 all-to-all 流量远高于其他卡。all-to-all 是集合通信,所有卡都要参与,慢卡会拖住整个集合操作。

两层叠加,稀疏计算省下的 FLOPs 被最慢卡的等待时间抵消。工程上常见的应对是容量因子(capacity factor):给每个专家设一个 token 上限,超出部分丢弃或截断。这能把负载拉平,但代价是丢 token。MegaBlocks 的论文正是针对这一权衡:现有框架为满足软硬件约束限制动态路由,迫使用户在“丢 token”和“用 padding 浪费计算与内存”之间二选一。MegaBlocks 把 MoE 计算重构为块稀疏操作,做到不丢 token 且高效映射到硬件。

容量因子、专家复制与 dropless 的取舍

面对负载不均,有三条常见路线,它们的代价结构不同。

容量因子调优是改动最小的。给每个专家设固定 token 预算,溢出丢弃或 padding。容量因子调大,丢 token 少但 padding 多、计算浪费;调小则相反。它把动态路由约束成规整形状,硬件友好,但直接牺牲模型质量或算力。

专家复制是把热门专家在多个卡上放副本,让 token 就近路由,减少跨卡流量和热点。代价是显存占用上升,且副本之间需要同步权重,训练时还要处理梯度聚合。推理场景下权重同步压力小,复制更可行。

Dropless 路线不丢 token、不 padding,用块稀疏 kernel 和 grouped GEMM 直接处理变长 token 数。MegaBlocks 展示了这条路线在训练上相对 Tutel 库最高 40% 的端到端加速。NVIDIA Transformer Engine 在 JAX 上进一步用 grouped GEMM kernel 在单次调用中处理变长专家 token 数,并用 NCCL EP 融合 dispatch 与 combine、对 token 去重以减少网络流量。这些都是针对 ragged 与通信的专门优化。

三条路线的对比可以整理如下:

方案主要收益主要代价适用场景
容量因子调优形状规整,实现简单,硬件友好丢 token 或 padding 浪费,质量与效率二选一训练早期、对实现复杂度敏感
专家复制降低跨卡流量与热点,减少等待显存占用上升,副本权重需同步推理服务、热门专家集中且显存有余
Dropless(块稀疏/grouped GEMM)不丢 token,保留质量需要专门 kernel,实现复杂大规模训练、质量优先

需要说明的是,这些收益数字来自各自论文的特定实验设置,不能直接外推到你的部署。定性结论是:容量因子用质量换规整,复制用显存换通信,dropless 用实现复杂度换质量与效率兼得。

可观测指标与故障定位

延迟上升时,先确认瓶颈在哪一段,而不是直接调专家数。建议采集以下信号:

  • 每层 all-to-all 的耗时占该层总耗时比例。若接近或超过一半,通信是主导项。
  • 每张卡每层发送与接收的 token 数,观察最大值与最小值的比值。比值大说明负载不均。
  • 每个专家的 token 计数分布,识别长期过热或过冷的专家。
  • 每卡专家计算时间,定位最慢卡。
  • 跨卡 token 比例,即落在非本卡专家的 token 占比。这个值随专家数上升是延迟恶化的直接信号。

定位顺序可以是:先看 all-to-all 占比确认通信是否主导;再看每卡收发 token 比的离散度确认是否负载不均;最后看跨卡比例确认是否专家映射导致流量上升。如果 all-to-all 占比高但各卡收发均衡,问题在通信总量,考虑专家复制或调整映射;如果占比高且离散度大,问题在负载不均,考虑容量因子或复制热门专家。

一个容易忽略的点是 batch 大小。在线推理 batch 小,通信的固定开销(元数据、同步、kernel 启动)占比更高,专家数增加带来的碎片化更明显。增大 batch 能摊薄通信,但会增加排队延迟。这个权衡需要按服务的延迟目标来定。

适用边界与仍未解决的问题

专家并行并非在所有规模下都划算。当 EP 组较小、专家数远大于卡数、路由分布较均衡时,跨卡比例低,通信可控,稀疏计算收益能兑现。当 EP 组跨节点、走 InfiniBand 而非 NVLink 时,all-to-all 带宽下降,通信瓶颈更早出现。NVIDIA 博客提到其优化栈在 1024 卡、GB300 NVL72 上训练 DeepSeek-V3 671B 时达到 97% 扩展效率,但这是经过 grouped GEMM、NCCL EP 融合、去重、host offloading 和多流重叠等一系列针对性优化后的结果,不是默认配置能达到的。

仍未解决的问题包括:路由偏斜在推理时如何低成本纠正,而不引入训练时的辅助损失;专家复制后副本间的一致性如何在不增加同步延迟的前提下维持;dropless kernel 在极小 batch 下是否仍比容量因子方案划算。这些问题没有普适答案,取决于模型、硬件拓扑和服务延迟目标。

回到开头的反直觉结果:专家数增加本身不必然降低延迟。真正决定延迟的是跨卡 token 流动量、最慢卡的负载和 all-to-all 的绝对耗时。扩容前先量这三个量,再决定是加专家、加复制还是调容量因子。

资料来源

  1. DeepSpeed-MoE: Advancing Mixture-of-Experts Inference and Training to Power Next-Generation AI Scale
  2. MegaBlocks: Efficient Sparse Training with Mixture-of-Experts
  3. GShard: Scaling Giant Models with Conditional Computation and Automatic Sharding
  4. Accelerating Dropless MoE Training in JAX with NVIDIA Transformer Engine | NVIDIA Technical Blog