flowchart LR
subgraph ExpertParallel["专家并行 (EP) 拓扑"]
Tokens["输入序列 Tokens"] --> Gate["门控网络 Top-K Routing"]
Gate -->|分发| E0["GPU 0: 专家 0, 1"]
Gate -->|分发| E1["GPU 1: 专家 2, 3"]
Gate -->|分发| E2["GPU 2: 专家 4, 5"]
Gate -->|分发| E3["GPU 3: 专家 6, 7"]
end
第 10 课:专家并行 EP
参考答案版:包含完整代码实现与问答题深度参考解析。建议先独立完成练习题后再展开核对。
代码 4 分、Q1~Q3 各 2 分,通过线 8/10。必须解释正确性边界、显存/通信公式中的单位与分片维度;未实际运行的内容只能标记为静态审查。
- 对应官方章节:Expert Parallelism
- 前置:第 3 课(all-to-all 概念)、《Switch Transformers》等 MoE 基础(教材要求读者先了解 MoE)
- 状态:未开始
本课目标
完成后你需要能够:
- 说明 MoE 层的基本结构与 EP 的切分方式(专家维,不是 token 维)。
- 解释 EP 为什么必须与 DP 组合,以及与 TP 相比”轻量”在哪。
- 推演 token 路由产生的 all-to-all 通信与负载不均问题。
- 解释 DeepSeek-V3 的节点限制路由(每 token ≤ M 个节点)的设计动机。
核心概念
1. 混合专家架构(MoE)与专家并行(EP)的本质语义
混合专家模型(Mixture-of-Experts, MoE)是当前前沿大模型(如 DeepSeek-V3/R1、Mixtral、Grok)实现“超级参数容量(Trillion-scale Parameters)”与“可控计算预算(Constant FLOPs)”解耦的核心技术。
在标准 Transformer 架构中,全连接层(FFN/MLP)消耗了全网约 的参数量。MoE 将单一密集的 FFN 替换为一个门控路由网络(Gating Router)与 个结构同构的独立专家网络(Expert FFNs):
给定输入 Token 特征向量 ,Router 计算该 Token 对各专家的匹配亲和度分数:
系统仅激活得分最高的 个专家(如 Top-2,或 DeepSeek-V3 的 Top-8 细粒度专家),最终输出为激活专家输出的加权求和:
专家并行(Expert Parallelism, EP)的切分维度: 如图 10-1 所示,EP 既不切分矩阵乘法(不同于 TP),也不切分序列层深(不同于 PP),而是沿着“专家索引维度(Expert Dimension)”进行切分:
图 10-1:MoE 门控路由网络与跨 GPU 专家切分架构
- 设集群中有 张 GPU,模型拥有 个专家,则每张 GPU 常驻持有 个完整的专家模型权重。
- 与张量并行(TP)的关键区别:
- 在 TP 中,算子权重矩阵被强行拆散,各卡执行局部矩阵乘并产出“不完整的碎片(部分和 Partial Sum)”,必须通过阻塞式 AllReduce 沿特征维累加求和。
- 在 EP 中,每张 GPU 上的专家权重是 100% 完整且独立的!矩阵乘法在本地全量执行。EP 的本质是“计算不动,数据动”——根据 Router 的决策,将不同卡上的 Token 动态投递搬迁到对应专家所在的 GPU 上。
2. 为什么 EP 必须与数据并行(DP)深度绑定(2D 网格)
大模型中除了 MoE FFN 层之外,还包含大量的密集模块(Dense Layers):Embedding 词表、多头自注意力(Attention)、RMSNorm 归一化等。
如果仅仅孤立地做专家并行而不引入数据并行:
- 整个集群只能处理单份样本,这会导致所有 GPU 必须在非 MoE 区域完全冗余地重复计算相同的 Token 特征,造成严重的算力雪崩。
- 因此,工业界标准架构必然采用 二维网格拓扑:
- 在全局层面上,各个 GPU 接收互不重叠的批次样本(承担数据并行 DP 角色);
- 进入非 MoE 区域(如 Attention)时,各卡在本地独立前向计算;
- 一旦执行到 MoE 层,系统切换为 EP 语义:各卡本地样本产出的 Token 根据 Router 派发目标,跨卡重组并打散投递到各个专家卡上。
3. 双向 All-to-All 通信原语与流转闭环
如图 10-2 所示,一次 MoE 专家计算在底层严格由两次全交换(All-to-All)通信构成闭环:
sequenceDiagram
autonumber
participant Rank as 本地卡 (Rank i)
participant A2A_D as All-to-All Dispatch (分发)
participant Expert as 远端专家计算
participant A2A_C as All-to-All Combine (聚合)
Rank->>A2A_D: 发射分配给远端专家的 Tokens
A2A_D-->>Expert: 远端专家接收属于自己的 Tokens 并执行 MLP
Expert->>A2A_C: 将计算完成的隐藏状态发射回源卡
A2A_C-->>Rank: 源卡接收输出并按门控权重做加权求和
图 10-2:MoE 专家并行双向 All-to-All 通信与计算全流程
- 路由分发阶段(Dispatch All-to-All):
- 处于 Rank 的 GPU 拥有本地批次的 个 Token。通过本地 Router 算理,每个 Token 选出 个目标专家。
- 系统将发往远端各个 Rank 的 Token 特征向量分别打包(Pack)。
- 发起一次非均匀的全交换通信算子(
dist.all_to_all_single或带偏移量的 Ragged All-to-All): 每个 Rank 将本地收集的 Token 交换给持有对应专家的目标 GPU。
- 专家局部批量计算(Local Batched GEMM):
- 经过 All-to-All 后,每张 GPU 收到了来自全网各卡、且指名由自身管辖专家计算的所有 Token。
- GPU 将这些 Token 按本地专家索引分流聚类,调用 Grouped GEMM 连续执行前向推理。
- 结果汇聚送回阶段(Combine All-to-All):
- 本地专家计算完毕后,产出的特征张量必须原路返回其“发源地”Rank!
- 系统再次发射反向的 All-to-All,将特征向量送回原始 Token 所在的 GPU。
- 门控加权求和(Weighted Summation):
- 原始 GPU 收到返回的 个专家计算结果后,乘上第一步中留存的门控权重 ,累加合并后输出,无缝接入下一层网络。
单步单层 MoE 的通信量严格为:
4. 木桶效应:专家负载失衡(Load Imbalance)与应对演进
在理想状态下,每个专家接收到的 Token 数量均等,各卡计算耗时一致。但在真实语言分布中,某些专家(如处理标点符号、高频词)会被频繁路由,而专业领域的专家被选中极少。
木桶短板灾难(The Straggler Problem): 若专家 0 接收到 10 倍于均值的 Token,则持有专家 0 的 GPU 计算耗时将飙升 10 倍。而在分布式执行中,第二阶段的 Combine All-to-All 必须等待最慢的卡算完才能汇聚!单卡过载将拖垮整个万卡集群的时钟步长。
经典对抗方案:
- 负载均衡辅助损失(Auxiliary Loss):在总损失中加入正则项 ( 为路由频率, 为概率均值),惩罚扎堆现象。但强加 Aux Loss 往往会损伤模型的语言建模精度。
- 容量因子截断(Capacity Factor, CF):为每个专家设置缓冲上限 。超出上限的 Token 直接被强行丢弃(Drop Tokens)或旁路跳过。虽然保证了计算时间确定,但在推理和长推理时丢 Token 会引发严峻的幻觉。
5. 架构革新:节点限制路由(Node-Limited Routing,DeepSeek-V3 核心发明)
在大规模跨机训练中(如 2048 卡),全量 All-to-All 会对数据中心机间交换机网络造成近乎崩溃的横断面流量压力(East-West Bisection Bandwidth)。如果一个 Token 激活了 8 个专家,且这 8 个专家散落在 8 个不同的物理机柜中,该 Token 将产生 8 次跨机网络传输!
DeepSeek-V3 提出了颠覆性的 节点限制路由(Node-Limited Routing):
- 核心约束:在选择 Top-(如 )个专家时,强制施加硬件拓扑亲和性约束——每个 Token 选出的所有专家,最多只能分布在 个物理节点之内(例如 )。
- 系统红利:
- 路由选择被高概率锚定在机内(NVLink 域)或极少数跨机节点内。
- 极大地将跨节点 RDMA 网络通信流量截留或压缩了近 50%!
- 彻底规避了网络链路争抢和交换机拥塞,使万卡规模下的 EP 吞吐提升至前所未有的高度。
具体演示与数值推演
设集群规模为 2 张 GPU(Rank 0 与 Rank 1),模型共配置 4 个专家(每张卡部署 2 个专家:Rank 0 持有 Expert 0, 1;Rank 1 持有 Expert 2, 3)。总批次输入 16 个 Token:
- 理想均匀路由分布(Balanced Routing):
- 4 个专家各分得 4 个 Token(即
[4, 4, 4, 4])。 - Rank 0 的专家计算负载: 个 Token;
- Rank 1 的专家计算负载: 个 Token;
- 失衡比(Imbalance Ratio):(完美线性加速)。
- 4 个专家各分得 4 个 Token(即
- 极端失衡路由分布(Skewed Routing):
- 专家 0 成为热门专家,分得 10 个 Token;其余专家分别分得 4, 4, 2 个 Token(即
[10, 4, 4, 2])。 - Rank 0 的专家计算负载: 个 Token;
- Rank 1 的专家计算负载: 个 Token;
- 失衡比:。
- 耗时推演:由于跨卡 Combine All-to-All 必须等待 Rank 0 算完全部 14 个 Token,Rank 1 即使早已算完 6 个 Token 也必须在网络同步点挂起等待。整步耗时由 14 决定,硬件整体有效算力利用率暴跌至 。
- 专家 0 成为热门专家,分得 10 个 Token;其余专家分别分得 4, 4, 2 个 Token(即
代码填空题
模拟专家到 rank 的映射、负载统计与路由通信量。
Code
def expert_to_rank(num_experts: int, experts_per_rank: int) -> dict[int, int]:
"""专家均匀分到各 rank:rank r 持有专家 [r*e, (r+1)*e)。"""
mapping = {}
for e in range(num_experts):
mapping[e] = ______ # 填空:专家 e 所属的 rank
return mapping
def load_per_rank(tokens_per_expert: list[int], experts_per_rank: int) -> list[int]:
"""每 rank 的专家负载 = 其专家收到的 token 总数。"""
num_experts = len(tokens_per_expert)
rank_load = [0] * (num_experts // experts_per_rank)
for e, tokens in enumerate(tokens_per_expert):
r = expert_to_rank(num_experts, experts_per_rank)[e]
rank_load[r] += ______ # 填空:累加
return rank_load
def imbalance(loads: list[int]) -> float:
"""失衡比 = 最大负载 / 平均负载。"""
return ______ # 填空
def routing_volume(tokens_per_expert: list[int]) -> int:
"""
一次前向的 all-to-all 通信量(token 数)。
每个 token 都被路由到其目标专家所在 rank——注意目标专家可能就在本地
rank(这部分不需要网络传输)。严格计算要区分本地/远程;
这里先返回"被路由的 token 总数"作为上界,远程占比写在注释里。
"""
return ______ # 填空
if __name__ == "__main__":
# 均匀路由:每专家 4 token
tokens = [4, 4, 4, 4]
print("均匀:", load_per_rank(tokens, 2), "失衡比", f"{imbalance(load_per_rank(tokens, 2)):.2f}")
# 失衡路由:专家 0 拿到 10 个
tokens2 = [10, 4, 4, 2]
loads = load_per_rank(tokens2, 2)
print("失衡:", loads, "失衡比", f"{imbalance(loads):.2f}")
print("路由总量:", routing_volume(tokens2), "token")
# DeepSeek-V3 量级:256 专家、每卡 8 卡节点内放若干专家
print("专家映射示例:", expert_to_rank(256, 32)) # 每 rank 32 个专家三个问答题
Q1
为什么说 EP “比 TP 轻量”?两类并行各自传输的数据分别是什么(部分和 vs token 搬运)?为什么 EP 单独使用会造成非 MoE 部分的重复计算,必须与 DP 组合?
Q2
EP 的 all-to-all 通信发生在什么时机、传输什么数据?DeepSeek-V3 为什么限制”每个 token 最多送往 M=4 个节点”?这个约束与”均匀路由”的目标有什么区别与联系?
Q3
负载不均为什么是 EP 的致命问题(对比 DP 中负载天然均匀)?请列出至少两种缓解手段,并说明它们各自的代价。极端失衡(某专家 token 数超过容量)时会发生什么?
检查与通过标准
总分 10 分:代码正确 4 分(映射、负载、失衡比、路由量)、三题各 2 分、通过线 8 分。
一票否决项:
- 认为 EP 切分的是 token 维或输入 batch(那是 DP/CP)。
- 认为 EP 不需要与 DP 组合。
- 把 EP 通信说成 all-reduce 权重同步(是 all-to-all 路由)。
- 意识不到负载均衡问题及其与路由设计的耦合。