MoE 的几百个专家放在哪?token 怎么送过去?
这是一堂岔路课。第 4 课的 DualPipe 说它要把「专家并行的 all-to-all」藏起来。这个 all-to-all 从哪来?MoE 本身(为什么这样设计、专家怎么不抢活)是 C11 的主题;这一课只回答一个系统问题。
本课一问:MoE 有几百个专家,放在哪?每个 token 怎么送到它选中的专家那里?
这一课先不碰:路由为什么是 top-k、负载均衡怎么做(C11);MoE 省了什么算力(C11)。
从已有出发
切什么每张卡一份完整模型,各算全局 batch 的 1/N;反向之后把 N 份梯度加起来,每张卡用同一份梯度更新。
多出的通信all-reduce 梯度
有多大锚点 BF16 梯度 55.6 GB;8 卡 ring all-reduce 每卡每步发 97.2 GB。
切什么优化器状态、梯度、参数按 N 份切开,每张卡只存、只更新自己那份;ZeRO-3 在用到一层之前把这一层的参数拼回来。
多出的通信reduce-scatter 梯度 + all-gather 参数
有多大8 卡 ZeRO-3:每卡模型状态 55.6 GB(原来 444.5 GB);通信每卡每步 145.9 GB,是 DP 的 1.5 倍。
切什么一层里的矩阵乘拆给 t 张卡:第一个矩阵按列切、第二个按行切,非线性各算各的,最后一次 all-reduce。
多出的通信每层 all-reduce(前向 2 次、反向 2 次)
有多大t = 8、每 4,096 个 token:每卡发 18.8 GB,每层都要等它做完;所以只放在一台机的 8 张卡里。
切什么把 64 层按顺序切成 p 段放在不同的卡上,每段做完把激活交给下一段,反向时再把梯度传回来。
多出的通信段与段之间 send / recv 激活
有多大锚点每段 8 层(p = 8);每个 micro-batch(4,096 个 token)在段间传 0.0 GB 激活;代价是气泡:p = 8、m = 32 时 21.9%。
切什么一条很长的序列切给几张卡,每张卡只存自己那段 token 的激活;注意力需要全部 K、V,就让 K、V 块沿环传一圈。
多出的通信注意力里沿环传 K、V
有多大s = 131,072、8 卡:每张卡每一步传出一块 K、V 0.1 GB,每个全注意力层传 7 块。
切什么MoE 的专家分到不同卡上,token 用 all-to-all 发到持有对应专家的卡,算完再 all-to-all 收回来。
多出的通信FFN 前后各一次 all-to-all
有多大DeepSeek-V3:256 个路由专家 ÷ 64 张卡 = 每卡每层 4 个;每个 token 最多去 4 个节点。
只需要 MoE 的一个事实(C11 会从头讲):MoE 把每层的一个大 FFN 换成很多个小 FFN(专家),每个 token 由一个路由器挑出其中几个来算。DeepSeek-V3 的官方 config:61 层里前 3 层是普通 FFN,其余 58 层每层 256 个路由专家(另有 1 个共享专家),每个 token 选 8 个;每个专家是 3 × 7,168 × 2,048 = 44,040,192 个参数。
这一课的组件用合成的路由打分(没有真实模型的路由数据),贯穿例句不出场。
先自己设计:每张卡放一份全部专家
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
| DeepSeek-V3 · 路由专家 | 数 |
|---|---|
| 每个专家(gate、up、down 三个矩阵) | 3 × 7,168 × 2,048 = 44,040,192 |
| 每层 256 个 | 11.27B |
| 58 个 MoE 层 | 653.9B,BF16 权重 1.31 TB |
数字口径:frontier-models.json 的 DeepSeek-V3 官方 config 现算。
每张卡只放一部分专家。DeepSeek-V3 用 64 路专家并行、跨 8 个节点 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条官方自报的配置:16 路 PP、跨 8 节点的 64 路 EP、ZeRO-1 DP。 出处DeepSeek-V3 报告 §3.2(本地 PDF) ↗ :256 ÷ 64 = 每卡每层 4 个专家。token 在哪张卡上算前面的注意力,就从哪张卡出发,被路由器分到的专家在哪张卡,就发到哪张卡——每张卡发给每张卡各一份,这就是 all-to-all:
MoE 层要两次:进专家之前发出去(dispatch),专家算完再收回来(combine)。这个做法最早由 GShard(2020)大规模使用,它在 2,048 块 TPU v3 上训练了超过 600B 参数的 MoE 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条摘要:超过 6,000 亿参数、2,048 块 TPU v3、4 天。 出处Lepikhin et al. 2020(GShard,需联网) ↗需联网 。
新的失败:token 要跨机
all-to-all 的麻烦在于跨机。每个 token 选 8 个专家,它们散在 8 个节点上;跨节点走 IB,只有节点内 NVLink 的约 1/3(DeepSeek-V3 报告:160 GB/s 对 50 GB/s)。报告写得很直白:跨节点专家并行让计算与通信的比例接近 1 : 1 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条原话是「an inefficient computation-to-communication ratio of approximately 1:1」;带宽数字是报告给的 H800 集群值。 出处DeepSeek-V3 报告 §3.2.1、§3.2.2 ↗ ——算多久,就要传多久。
DeepSeek-V3 的改进是 node-limited routing:每个 token 最多发往 M = 4 个节点。节点按「这个节点上最高的 K/M = 2 个亲和分数之和」挑,再在选中的节点里选 8 个专家 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条规则是报告原文;config 里对应 moe_n_group = 8、moe_topk_group = 4。「限 4 个节点对模型质量的影响」报告没有给出消融。 出处DeepSeek-V3 报告 §2.1.2、§3.2.2 ↗ 。下面用它的真实布局和路由规则,在合成打分上跑一遍:
试三件事:① 在「直接选前 8」下读直方图:8 个专家大多落在 5、6 个节点上(红柱是超过 4 个节点的 token);② 切到「先选 4 个节点」,最多 4 个节点,跨节点副本明显变少,每个节点平均分到约 2 个专家——报告里的 3.2 不是这个平均数,而是「每个节点最多选这么多也不增加 NVLink 开销」的余量(见下一段);③ 把「热门专家」调到 +2:0 号节点那张卡收到的 token 是平均的十几倍,all-to-all 要等它——这就是 C11 负载均衡要解决的问题。
每个跨节点副本到了目标节点,再由 NVLink 转发给具体持有专家的那张卡;报告说这样 IB 与 NVLink 的传输可以完全重叠,每个 token 平均在每个节点选 3.2 个专家也不增加 NVLink 的开销——换句话说,同样的通信成本最多能支持 4 × 3.2 ≈ 13 个专家。发出去的激活先量化成 FP8,收回来的保留 BF16;整套通信只占 20 个 SM 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条全部是报告对自己实现的描述。 出处DeepSeek-V3 报告 §3.2.2、§3.3.3 ↗ 。
最后一招:把 all-to-all 藏到另一批计算后面
限了节点,通信还是很重。DeepSeek-V3 的 DualPipe(第 4 课)把一个前向块和一个反向块配成一对:把每个块拆成注意力、dispatch、MLP、combine 几段,让这一个块的 all-to-all 和另一个块的计算同时进行,报告称 all-to-all 与流水线通信都可以「完全隐藏」 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条报告的自述;只要计算与通信的比例保持不变,放大模型时仍能用细粒度专家而几乎不付 all-to-all 的开销。 出处DeepSeek-V3 报告 §3.2.1 图 4 ↗ 。这和第 1 课「分桶把梯度同步藏到反向后面」是同一种思路,只是这次藏的是 token。
常见误解之一:「专家并行和数据并行只能二选一。」
DeepSeek-V3 同时用 64 路专家并行、16 路流水线并行和 ZeRO-1 数据并行:专家按 EP 切,其余部分(注意力、共享专家)照常做数据并行。实验课会看到几维怎么叠。
常见误解之二:「MoE 省算力,所以也省显存和通信。」
MoE 省的是每个 token 的计算(只算 8 个专家);全部 256 个专家的参数都要放下,token 还要跨卡跑两趟。显存靠专家并行摊开,通信靠限节点和重叠去藏。
常见误解之三:「限制每个 token 最多去 4 个节点,一定会让模型变差。」
报告没有给出这项限制对质量的消融,这里只能说「不知道」;它给出的是工程上的动机(IB 只有 NVLink 的约 1/3)和「训练中不丢任何 token」的结果。
证据三问
| 问 | 本课的回答 |
|---|---|
| ① 它解决什么问题? | MoE 的专家太多,每张卡放不下全部;把专家分到各卡,token 发过去算 |
| ② 数学上为什么可能有效? | 每个专家只处理分给它的 token,专家之间互不相干,所以可以放在不同的卡上;通信量由路由决定,限节点直接截断了跨机副本数的上限 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条「每个 token 最多 M 个跨节点副本」按规则构造成立;组件里的直方图最多到 4 就是这个事实。 出处待补 |
| ③ 实验上为什么最后选了它? | GShard 首先在 600B 规模上用它;DeepSeek-V3 用 64 路 EP 加限节点与 DualPipe 训完了 671B 的模型,报告称训练中没有丢 token 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条官方自报。 出处GShard 摘要;DeepSeek-V3 §2.1.2、§3.2 ↗ |
演进地图:你在这里
- 解决了训练一步的全部东西都在一张卡上,不需要任何通信。卡在锚点的模型状态 16 字节 × 27,781,427,952 = 444.5 GB,是 80 GB 的 5.6 倍;就算放得下也太慢:DeepSeek-V3 预训练用了 2,664K H800 GPU 小时,一张卡约 304 年。
- 解决了每卡一份完整模型、算 1/N 的数据,每步把梯度加起来。ring 让每卡只收发 2(N−1)/N 倍梯度:锚点 8 卡 97.2 GB、64 卡 109.4 GB(汇总到 0 号卡的朴素做法:388.9 GB → 3,500 GB)。卡在只解决「慢」:每张卡仍要放下完整的 444.5 GB。
- 解决了反向逐层产出梯度,攒满一桶(默认 25 MiB)就先发,通信藏到后面几层的反向里。卡在DP 的通信量每步固定:锚点 8 卡每卡 97.2 GB,按 IB 50 GB/s 要 1.94 s;每卡 4,096 个 token 的反向只有约 1.05 s(推演)——token 太少就藏不住。
- 解决了不再每卡存一份:8 卡上 444.5 → 152.8 → 104.2 → 55.6 GB(依次切优化器状态、梯度、参数)。卡在切参数后每步多一次 all-gather,通信是 DP 的 1.5 倍;激活不切:s = 4,096 的选择性重计算要 45.6 GB,放不进剩下的 24.4 GB。
- 解决了第一个矩阵按列切、第二个按行切,一个 MLP 只要一次 all-reduce;t = 8 配序列并行,激活 45.6 → 5.7 GB。卡在每层前向 2 次、反向 2 次同步:每 4,096 个 token 每卡要发 18.8 GB,每层都要等——只能放在机内。ZeRO 原文实测:跨两台 DGX-2,每卡约 5 TFLOPS,不到峰值 5%。
- 解决了按层切,跨机只传段与段之间的激活;切 micro-batch 填满流水线;1F1B 把在途激活从 m 份压到 p 份;interleaved 把气泡除以 v。卡在首尾必然空等:p = 8、m = 32 时气泡 (p−1)/m = 21.9%(占总时间 17.9%),interleaved v = 4 也还有 5.5%。
- 解决了反向拆成「对输入」B 与「对权重」W,W 拿去填空泡(F = B = W 时 ZB-H1 的气泡是 1F1B 的 1/3);DualPipe 从两头喂 micro-batch,并把 all-to-all 藏到另一批计算后面。卡在DualPipe 要存两份参数;调度更复杂;通信只是被藏住了,量一点没少。
- 解决了128K 的序列按序列切给多张卡;zig-zag 头尾配对,把因果负载 10 : 26 : 42 : 58 配平成每卡一样多。卡在每个全注意力层都要在卡之间传 K、V:锚点 s = 131,072、8 卡时每层 0.5 GB;Ulysses 按头切,KV 只有 4 个头。
- 解决了DeepSeek-V3 的 654B 路由专家参数分到 64 张卡,每卡每层 4 个;每个 token 最多去 4 个节点。卡在跨节点 IB 50 GB/s 只有 NVLink 160 GB/s 的约 1/3,跨节点 EP 的计算与通信约 1 : 1;热门专家所在的卡成为掉队者(→ C11)。
- 解决了Llama 3 405B:[TP, CP, PP, DP] = 8 × 1 × 16 × 128,16,384 张 H100,BF16 MFU 41%;DeepSeek-V3:PP 16 × EP 64 × ZeRO-1 DP,不用 TP。卡在没有万能配置:每种组合都要先算清每卡显存、每一维的通信走哪条链路、气泡多大(实验课)。
一句话
专家并行把专家分到不同卡,用两次 all-to-all 把 token 送去再收回;跨节点带宽只有节点内的约 1/3,所以 DeepSeek-V3 让每个 token 最多去 4 个节点,再用 DualPipe 把通信藏到另一批计算后面。
回到主线
实验课:几种切法怎么组合成一套方案? → 实验课。MoE 本身——为什么用它、专家为什么会抢活、专家该大还是小——在 C11。
你可能会问
- 「热门专家的卡掉队,能不能多放几个副本?」 推理部署时 DeepSeek-V3 就这么做(冗余专家,报告 §3.4);训练时它靠无辅助损失的负载均衡让各专家的负载本身接近平均(C11)。
- 「共享专家也要 all-to-all 吗?」 按结构不需要:每个 token 都要过共享专家,不用路由,可以像注意力一样就在 token 所在的卡上算。但这是工程选择——DeepSeek-V3 在推理的解码阶段反过来把共享专家当成一个「每次必选」的路由专家来部署(报告 §3.4.2)。
- 「all-to-all 和 all-reduce 的流量一样吗?」 不一样。all-to-all 每张卡发出 (N−1)/N 份自己的数据、不做加法;all-reduce 发出约 2 倍、要求和。all-to-all 的量取决于路由,可能严重不均——这正是掉队者的来源。