mindspore-ai / mindspore-ai/hyper-parallel
【RFC】EP 通算掩盖:共享专家重叠、DualPipe 与 W/D 掩盖
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 53
- Forks
- 63
- Avg merge
- 23h 45m
- Merged PRs (30d)
- 63
Description
EP 通算掩盖:共享专家重叠、1F1B 通算掩盖、W/D 拆分与 DualPipe
本文档描述 Expert Parallel 的四类计算与通信重叠优化:
- A — 共享专家与 combine 通信的异步重叠(本期目标)
- B — 1F1B 通算掩盖:BWD ↔ FWD a2a 跨线程交错(Phase 1,参考实现已落在
examples/torch/pp_overlap/pp_overlap_moe_example.py,待产品化) - C — W/D 拆分 + deferred W 队列(Phase 2,本文档仅定义范围,本期不实施)
- D — 双向流水线 DualPipe(远期规划,本文档仅说明情况)
侧重背景、职责边界、接口与契约、测试与验收,不包含具体代码实现。
1. 背景
1.1 EP 通信的时序瓶颈
标准 EP 的 forward 执行时序为:
dispatch all-to-all ─→ 本地 expert 计算 ─→ combine all-to-all
三阶段串行执行,计算与通信完全顺序。在 ep_degree 较大、机间带宽受限时,两次 all-to-all 的时延直接叠加在关键路径上,成为 MoE 层的主要耗时。反向链路上还会再叠加 combine_bwd 与 dispatch_bwd 两次 a2a,通信总量比前向更大。
1.2 已有基础与缺口
已实现:
AllToAllTokenDispatcher.dispatch()与combine()的基础流程(同步 all-to-all);MoE内的shared_expert(可选FeedForward,输出与 expert 输出相加);platform.differentiable_all_to_all_single同步版本;platform.differentiable_all_to_all_single_async异步版本(已在 example 中验证);CommComputeOverlap多线程通算协调器与 A/B/C/D 同步 hook 原语(example 中使用);ScheduleInterleaved1F1B(overlap_b_f=True)调度器,能在 1F1B 稳态发出OVERLAP_B_F复合步。
缺口:
shared_expert与combineall-to-all 串行执行(A 的目标);ExpertParallel把_input_splits / _output_splits / _input_shape / _permuted_indices挂在 EP 实例上,跨层只能靠"每层一个 EP 实例"绕开,跨 microbatch 不安全(B 产品化前置);- example 仅 Torch + NPU 实测,未跨平台对齐;
- 缺少把反向拆成 D 段 / W 段、并把 W 段移入通信等待窗口的机制(C);
- 缺少双向流水线调度(D)。
2. 四类优化的定义与范围
2.1 子方向 A:共享专家与 combine 通信异步重叠
核心思想:
combine all-to-all 发起后,在等待通信结果的时间窗口内,并行执行 shared expert 的前向计算,将两者的时延进行掩盖。
时序对比:
当前(串行):
combine all-to-all ──────────► 完成
shared_expert 计算 ──► sum
目标(重叠):
combine all-to-all ─────────────────────► 完成 ─► sum
shared_expert 计算 ────────────────► (与通信并行)
依赖:
platform.differentiable_all_to_all_single支持异步发起,返回句柄(AsyncHandle);TokenDispatcher.combine()分解为「发起」和「等待 + 合并」两个阶段;- shared_expert 在「发起」之后、「等待」之前执行。
2.2 子方向 B:1F1B 通算掩盖(BWD ↔ FWD a2a 跨线程交错)
核心思想:
ScheduleInterleaved1F1B 的 1F1B 稳态把 BWD microbatch i 与 FWD microbatch i+1(来自不同虚拟 chunk)打包成 OVERLAP_B_F 复合步,两条线程分别承载 FWD 与 BWD:
- 同一 ep_group 上的 a2a 由
CommComputeOverlap的协调器全局串行(同 group 两个 a2a 并发会触发 HCCL 数据损坏); - 通信占用通信流时,对侧线程的计算占用计算流,通过"通信 vs 计算"在不同流上并行完成掩盖;
- A/B/C/D 4 个
differentiable_sync_hook把 dispatch a2a 和 combine a2a 各自夹在一对 hook 中间,hook 之间是 compute 区,coordinator 在 hook 上交接 HCCL 发射权。
时序示意(一对 BWD↔FWD 配对内的一层 MoE):
sequenceDiagram
participant CS as 计算流
participant CO as Coordinator
participant XS as 通信流(HCCL)<br/>同 ep_group 全局串行
Note over CS,XS: 配对开始<br/>FWD microbatch i+1(MoE 层 L)<br/>BWD microbatch i(MoE 层 L+1,反向遍历)
rect rgb(220, 240, 220)
Note left of CS: 并发计算:<br/>BWD 上一层 expert_w 残段
CO->>XS: FWD dispatch a2a(hook A→B 内异步发射)
XS-->>CO: 完成
end
rect rgb(220, 240, 220)
Note left of CS: 并发计算:<br/>FWD permute + expert FFN(hook B 之后的 compute 区)
CO->>XS: BWD combine_bwd a2a 异步发射
XS-->>CO: 完成
end
rect rgb(220, 240, 220)
Note left of CS: 并发计算:<br/>BWD expert_bwd D 段
CO->>XS: FWD combine a2a(hook C→D 内异步发射)
XS-->>CO: 完成
end
rect rgb(220, 240, 220)
Note left of CS: 并发计算:<br/>FWD 下一层 attn / qkv
CO->>XS: BWD dispatch_bwd a2a 异步发射
XS-->>CO: 完成
end
Note over CS,XS: 进入下一对 BWD↔FWD 配对
注:上图为一对 BWD↔FWD 配对里 一层 MoE 的半周期 概念示意,重在表达「HCCL 同 ep_group 全局串行 + 对侧计算填窗」的资源占用模型。example 实际每 chunk 含 2 层 MoE(
moe_layers_per_chunk = 2,用于解锁跨层D → A_next的 attn 掩盖窗口),完整周期是 8 个 a2a 槽位;且 chunk 最后一层的 D hook 标为D_LAST,BWD 起点的combine_bwd自由发射、不参与 rendezvous,与中间层并不对称。每个槽位上「对侧 compute」的具体内容(如expert_w 残段/下一层 attn等标签)由HookCoordinator配对规则 + 两层 MoE 交错相位决定,图中标注为示意,可能存在 ±1 hook 的相位偏移。
与文档前一版「DualPipeExpertParallel」的关系:前一版用「Micro-batch N 的 combine 与 Micro-batch N+1 的 dispatch 在前向接力」描述 B,落到 HCCL/NCCL 上同 group 两 a2a 无法真正并发,需要 BWD 同时在场才能用 BWD 的计算去掩盖 FWD 的通信。example 的实现是这一观察的工程化产物,与 DeepSeek 完整 DualPipe(见 2.4)不同,没有双向流水线、没有 chunk 内 4 段细粒度切分、没有 W/D 拆分,但已能拿到主要收益。为避免名称混淆,本期内部命名采用 OverlapExpertParallel + CommComputeOverlap + ScheduleInterleaved1F1B(overlap_b_f=True) 三件套,不再使用 "DualPipeExpertParallel" 这一名称。
依赖:
- 异步 a2a 接口(与 A 共用
platform.differentiable_all_to_all_single_async); CommComputeOverlap+differentiable_sync_hook("A"|"B"|"C"|"D"|"D_LAST")协调器;ScheduleInterleaved1F1B支持overlap_b_f=True/overlap_p2p=True;- MoE 层每层独立持有
_input_splits等状态(或迁移至DispatchMetadata栈式对象); - chunk 的最后一层 MoE 用
is_last_layer=True标记,使 D hook 退化为D_LAST(前向后无 attn、反向 combine_bwd 已自由发射,无需 rendezvous); - BWD 线程显式
set_device(local):current device 是 thread-local,缺失会让 HCCL 跑到 device 0 死锁。
2.3 子方向 C:W/D 拆分 + deferred W 队列(本期不实施,仅定义范围)
核心思想:
反向天然由 D = ∂L/∂x(输入梯度,传给上层)+ W = ∂L/∂w(权重梯度,本地消费)两部分组成。标准 autograd 把它们绑在同一个 backward node 一次性算完。W/D 拆分把它们解耦:
- D 段留在 backward 关键路径上,与 a2a 通信交错(B 已经做到这一步);
- W 段入 deferred 队列,由 pipeline scheduler 在仍未被掩盖的 comm 等待窗口里 flush。
时序示意:
flowchart TB
subgraph standard[标准反向(B 已实现的状态)]
direction LR
s1[layer L+1<br/>expert_bwd<br/>同时算 dX+dW] --> s2[a2a comm<br/>对侧 compute<br/>已被掩盖]
s2 --> s3[layer L<br/>expert_bwd<br/>同时算 dX+dW]
end
subgraph withwd[W/D 拆分反向]
direction LR
w1[layer L+1<br/>expert_bwd 仅 dX] --> w2[a2a comm 发射]
w1 -.W 任务入队<br/>持有激活.-> wq[(deferred<br/>W queue)]
w2 --> w4[layer L<br/>expert_bwd 仅 dX]
w4 -.W 任务入队.-> wq
w2 -.flush 填残余窗口.-> wq
end
style s2 fill:#ffe0b0
style wq fill:#c0e8c0
范围(一旦 Phase 2 立项需要改的面):
- 自定义 GEMM autograd:在
expert/attn_qkv/attn_proj/ffn关键 GEMM 上提供backward_d_only(grad_out, weight) → grad_in与backward_w_only(grad_out, input_saved) → grad_w两个独立入口,绕开标准 autograd 的「原子 backward」假设。 - deferred W 队列:挂在 pipeline scheduler 上,per-rank 一个;条目包含
(grad_out_ref, input_saved_ref, weight_ref, target_grad_buffer)。 - MoE / Attention / FFN 协作:backward 不再调用整块算子,而是按 D-only 调用 + 把 W 任务推入队列。
- flush 时机:在
OVERLAP_B_F复合步的 a2a 等待窗口里调度 W 任务;在 1F1B cooldown 阶段统一 drain 剩余 W。 - 激活生命周期:W 任务需要持有 forward 激活到任务执行为止,激活释放被推迟,显存上升是 W/D 的硬成本。
本期不实施的原因:
- 收益相对 B 是「填窗」性质,B 已掩盖主要通信;C 在 B 之上再提一档,但绝对值有限;
- 改动面跨 MoE / Attention / FFN / scheduler 四个模块,PR 体量大;
- 自定义 autograd 在 Torch / MindSpore 上需各写一套;
- 显存成本需要先在 Phase 1 上量化才能判断是否值得引入。
2.4 子方向 D:双向流水线 DualPipe(远期规划)
核心思想:
DeepSeek-V3 DualPipe 与本仓现状(含 B/C)的根本区别是 pipeline 调度:
- 标准 1F1B:单向流水,每个 rank 持有 1 个 stage 的参数,气泡 ≈
(P - 1) × (F + B); - DualPipe:双向流水,每个 rank 同时持有相邻 2 个 stage 的参数(正向流的 stage
k和反向流的 stage2P - 1 - k),来自两条对头 microbatch 流,气泡 ≈(P/2 - 1) × (F + B - 2W)。
每个 rank 任一时刻同时有一个 FWD microbatch 与一个 BWD microbatch 在场,且这两个 microbatch 来自不同方向的 pipeline 流、互无数据依赖,比 1F1B 稳态下「同条流的 BWD_i + FWD_{i+1}」并行度更高。
示意:
flowchart LR
subgraph baseline["标准 1F1B(单向)"]
direction LR
s0["rank 0<br/>stage 0"] --> s1["rank 1<br/>stage 1"] --> s2["rank 2<br/>stage 2"] --> s3["rank 3<br/>stage 3"]
s3 -.反向回传.-> s2
s2 -.-> s1
s1 -.-> s0
end
subgraph dualpipe["DualPipe(双向,每 rank 持 2 stage)"]
direction LR
d0["rank 0<br/>stage 0 (正)<br/>stage 7 (反)"]
d1["rank 1<br/>stage 1 (正)<br/>stage 6 (反)"]
d2["rank 2<br/>stage 2 (正)<br/>stage 5 (反)"]
d3["rank 3<br/>stage 3 (正)<br/>stage 4 (反)"]
d0 ==正向流==> d1 ==> d2 ==> d3
d3 ==反向流==> d2 ==> d1 ==> d0
end
style dualpipe fill:#eef
chunk 内 4 段交错:DualPipe 把每个 chunk 切成 ATTN / DISPATCH / MLP / COMBINE 四段,让 FWD chunk 的 comm 段与对头 BWD chunk 的 compute 段两两咬合,比 B 的 A/B/C/D 4 hook 粒度更细。
与 B/C 的关系:
- D 与 B 互不相同:B 是「单向 1F1B 上用 BWD 配 FWD」,D 是「双向流水线」,B 的 example 可视作 D 的同向简化版;
- D 强依赖 C 的 W/D 拆分:DualPipe 的气泡公式里那个
-2W项就是 W 段填洞带来的; - 双向流水线需要
core/pipeline_parallel/引入新调度器,与现有ScheduleInterleaved1F1B并列。
本期不立项的原因:
- 2× 参数显存:每 rank 持 2 个 stage 的参数,叠加 FSDP 后仍然实打实多一倍持久参数显存,对中等规模反而退化;
- 调度器需要重写,FSDP / EP / CP / activation checkpoint 全组合都要重测;
- 收益曲线在
pp_size ≥ 16的大规模 MoE 才显著,需要先有明确用户场景; - 决策点放在 Phase 2 完成后再评估,本文档仅保留概念。
3. 目标与非目标
3.1 目标(本期)
子方向 A(本期唯一交付项):
- 扩展
platform.differentiable_all_to_all_single,支持异步发起模式,返回AsyncHandle; AllToAllTokenDispatcher.combine()分解为combine_start()和combine_wait()(或通过DispatchMetadata携带句柄);MoE.forward在combine_start()和combine_wait()之间执行 shared_expert;- 无 shared_expert 时行为完全兼容(退化为同步路径)。
3.2 后续路线(按阶段排期,本期不交付)
Phase 1 — 子方向 B 产品化:
- 把
examples/torch/pp_overlap/pp_overlap_moe_example.py中的OverlapExpertParallel抬成正式 API,纳入hyper_parallel/core/expert_parallel/; - 状态从 EP 实例迁移至
DispatchMetadata或 MoE 模块,去掉「每层一个 EP 实例」的 workaround; - 跨平台对齐:补 MindSpore 路径;
- 完善 ST 矩阵(PP × EP × FSDP,含 D_LAST 边界、零 token 边界)。
Phase 2 — 子方向 C W/D 拆分:
- 自定义 GEMM autograd(先 Torch);
- deferred W 队列与
ScheduleInterleaved1F1B集成; - 量化激活显存上升与端到端收益,决定是否再做 MindSpore 路径。
Phase 3 — 子方向 D 评估:
- 仅当出现
pp_size ≥ 16的真实用户场景时立项; - 立项前先评估 2× 参数显存是否可接受。
3.3 非目标
- 不修改 attention 或 FFN 的计算逻辑(A/B 范围);
- 不在本期实现 B/C/D;
- 不引入 DeepEP / 自定义通信库。
4. 接口与契约
4.1 异步 all-to-all 平台接口(A 依赖)
platform.differentiable_all_to_all_single(
input_tensor, input_splits, output_splits, group,
async_op: bool = False,
) -> Tensor | (AsyncHandle, Tensor)
| 参数 | 说明 |
|---|---|
async_op=False(默认) |
同步执行,行为与当前实现完全兼容 |
async_op=True |
异步发起,返回 (handle, output_tensor);调用方须在使用 output_tensor 前调用 handle.wait() |
约束:
async_op=True时,output_tensor是已分配但未填充的 Tensor,访问需在handle.wait()后;handle.wait()是幂等的;- 平台抽象层(
platform/platform.py)需在抽象接口中声明此参数,PyTorch 和 MindSpore 分别实现; - Phase 1 复用同名
platform.differentiable_all_to_all_single_async,含义等价。
4.2 AllToAllTokenDispatcher 的分阶段 combine(A)
class AllToAllTokenDispatcher:
def combine_start(
self,
expert_output: Tensor,
top_scores: Tensor,
metadata: DispatchMetadata,
) -> (AsyncHandle, CombinePartialResult):
"""
发起 combine all-to-all(异步),返回句柄与中间状态。
不等待通信完成。
"""
def combine_wait(
self,
handle: AsyncHandle,
partial: CombinePartialResult,
) -> Tensor:
"""
等待 handle 完成,执行 unpermute + scatter_add,返回最终 combined tensor。
"""
CombinePartialResult 携带 unpermute 所需的中间状态,生命周期与本次 forward 调用绑定,不持有对 dispatcher 的引用。
向后兼容:保留 combine(expert_output, top_scores, metadata) 同步版本,内部调用 combine_start + combine_wait,对不需要 shared_expert 重叠的场景透明。
4.3 MoE.forward 的新时序(A)
# 1. Dispatch
permuted_input, local_counts, dispatch_meta = dispatcher.dispatch(x_flat, ...)
# 2. Expert 计算
expert_output = self.experts(permuted_input, local_counts)
# 3. 发起 combine(异步)
handle, combine_partial = dispatcher.combine_start(expert_output, top_scores, dispatch_meta)
# 4. Shared expert 计算(与 combine 通信并行)
shared_out = self.shared_expert(x_flat) if self.shared_expert else None
# 5. 等待 combine 完成
combined = dispatcher.combine_wait(handle, combine_partial)
# 6. 合并输出
out = combined + shared_out if shared_out is not None else combined
约束:
- 若无
shared_expert(shared_expert is None),步骤 3~5 退化为同步combine(),无额外开销; x_flat在步骤 4 中被 shared_expert 使用,需保证在步骤 3 发起通信后未被修改(即不可原地操作)。
4.4 B 参考实现接口(Phase 1 产品化目标)
example 已落地的 API(Phase 1 把它们从 example 移入 hyper_parallel/core/expert_parallel/):
class OverlapExpertParallel(ExpertParallel):
def __init__(self, overlap: CommComputeOverlap, is_last_layer: bool = False) -> None:
...
# forward / backward 入口照常,内部用 differentiable_sync_hook
# 把 dispatch a2a 夹在 A/B 之间、combine a2a 夹在 C/D(或 C/D_LAST)之间。
class CommComputeOverlap:
coordinator: HookCoordinator
def run(self, fwd_fn, bwd_fn) -> None: ... # 两线程执行 FWD + BWD
调度侧入口:
ScheduleInterleaved1F1B(stages, micro_batch_num, overlap_p2p=True, overlap_b_f=True)
schedule.register_custom_function(MetaStepType.OVERLAP_B_F, callback)
Phase 1 产品化要补:
- 状态去实例化:现有
OverlapExpertParallel仍把_input_splits / _output_splits / _input_shape / _permuted_indices写在自身上,跨 microbatch 不安全;改为通过DispatchMetadata显式回传给combine,与 4.2 的CombinePartialResult统一。 is_last_layer自动推断:例子里靠用户手动传,产品化要让框架从 chunk 结构自动判定。- MindSpore 路径:example 只跑了 Torch + NPU,需要补 MindSpore
differentiable_all_to_all_single_async与多线程协调器。 - 错误恢复:HCCL 错误下 coordinator 不能死锁(带超时 / 失败传播)。
4.5 C 接口草稿(Phase 2,本期不实现,供后续设计参考)
class GemmDeferred(torch.autograd.Function):
@staticmethod
def forward(ctx, input, weight): ...
@staticmethod
def backward(ctx, grad_out):
# 仅算 dX;把 dW 任务推入 ctx.deferred_w_queue
grad_in = ...
DeferredWQueue.current().push(ctx.input_saved, ctx.weight, grad_out, ctx.grad_w_slot)
return grad_in, None
class DeferredWQueue:
def push(self, input_saved, weight, grad_out, grad_w_slot): ...
def flush(self, deadline_event): ...
@classmethod
def current(cls) -> "DeferredWQueue": ...
约束:
- 队列条目持有 forward 激活(
input_saved),生命周期由调度器管理; flush(deadline_event)在 a2a 等待窗口里调用,事件触发时停止入队;- 1F1B cooldown 时统一 drain;
- MoE 的 GroupedExperts 需要把
expert_w注册到DeferredWQueue.current()。
4.6 D 接口草稿(远期,本期不实现)
class DualPipeSchedule(PipelineScheduleBase):
# 双向流水线:每 rank 持 2 stage,正反两条 microbatch 流。
# chunk 切成 ATTN / DISPATCH / MLP / COMBINE 四段。
# 复合步:FwdSlice(direction=↓) ⊕ BwdSlice(direction=↑) 对头配对。
...
前置条件:
- 子方向 C 完成(W 段提供填洞料源);
- Pipeline scheduler 框架允许同 rank 持有多 stage 参数。
4.7 平台支持矩阵
| 平台 | A(异步 a2a + shared_expert 重叠) | B(1F1B 通算掩盖) | C(W/D 拆分) | D(DualPipe) |
|---|---|---|---|---|
| PyTorch / CUDA | ✅ 本期目标 | Phase 1 验证 | Phase 2 | Phase 3 评估 |
| Ascend NPU / CANN | ✅ 本期目标 | ✅ example 已验证,Phase 1 产品化 | Phase 2 | Phase 3 评估 |
| MindSpore | ⬜ 待 MindSpore EP 支持后评估 | Phase 1 补齐 | Phase 2 评估 | — |
5. 测试设计
5.1 子方向 A 单元测试
| 用例 ID | 描述 | 期望 |
|---|---|---|
| OV-01 | combine_start + combine_wait round-trip,无 shared_expert |
输出与同步 combine() 数值完全一致 |
| OV-02 | 无 shared_expert 时,同步退化路径执行 | 与当前 EP 基线一致,无性能退化 |
| OV-03 | handle.wait() 幂等性:调用两次不报错 |
第二次调用安全返回 |
| OV-04 | shared_expert 在 combine 通信期间执行(模拟通信延迟) | 两者时序正确,最终输出与串行执行数值一致 |
5.2 子方向 A 分布式测试
| 用例 ID | 配置 | 期望 |
|---|---|---|
| OV-D01 | 4 卡 EP + shared_expert,异步 combine | 前向/反向输出与串行基线(同 token)数值对齐(rtol=1e-3) |
| OV-D02 | 性能对比:4 卡 EP,有/无 shared_expert 重叠 | 异步重叠版本的 MoE 层时延不高于串行版本(通过 profiling 验证) |
5.3 子方向 B 产品化验收要点(Phase 1)
| 用例 ID | 配置 | 期望 |
|---|---|---|
| OV-B01 | example 当前配置(PP=2, EP=2, 4 卡,2 chunks/rank,2 MoE/chunk) | 与无 overlap 基线数值对齐(rtol=1e-3) |
| OV-B02 | DispatchMetadata 化后,跨 microbatch 状态不互相覆盖 |
多 microbatch 顺序运行结果与单 microbatch 拼接一致 |
| OV-B03 | 零 token 边界:某 rank 在某 microbatch 收到 0 token | autograd 不断(不出现 "element 0 does not require grad") |
| OV-B04 | is_last_layer 自动推断与手动指定行为一致 |
输出与 baseline 数值对齐 |
| OV-B05 | MindSpore 路径数值对齐 | 与 Torch 路径同 seed 下 rtol=1e-3 |
| OV-B06 | Profiling:a2a 与对侧 compute 实际重叠比例 | ≥ 60%(example 已观测数据为参照) |
5.4 子方向 C / D 验收
在各自后续设计文档定义,本文档不展开。指标方向:
- C:W/D 拆分后端到端 step 时延相对 B 的下降比例;激活显存上升幅度;
- D:与 B + C 组合相比的气泡公式实测,要求
pp_size = 16配置下下降到(P/2 - 1)量级。
5.5 回归
- 现有 8 个 EP 分布式 ST 测试(无 shared_expert,同步路径)无回归;
- 现有 5 个 shared_expert 相关 ST 测试无回归;
- example 当前能跑通的 4 卡 PP+EP 用例,A 落地后仍跑通。
6. 风险与开放问题
| 风险 | 缓解 |
|---|---|
| 异步 all-to-all 在 NPU CANN 版本上的 API 兼容性 | 平台层封装隔离,NPU 路径单独测试并锁定 CANN 版本 |
combine_start 后 x_flat 被 shared_expert 并发访问的内存安全 |
x_flat 为 combine 发起前的只读输入,dispatch 结束后不再修改,shared_expert 仅读取,无并发写冲突 |
| 异步 combine 反向梯度路径(autograd graph) | differentiable_all_to_all_single 的 autograd function 需与异步句柄的 wait() 正确绑定;backward 中 wait() 必须先于梯度计算 |
| B 跨 microbatch 状态污染 | Phase 1 强制把 _input_splits 等迁出 EP 实例,统一走 DispatchMetadata |
| B 协调器死锁(HCCL 错误 / 边界 microbatch) | D_LAST 标签 + 超时机制 + 失败传播;example 已踩过的坑(last layer 不 rendezvous、BWD 线程 set_device)必须复刻 |
| C 引入显存上升(deferred 激活) | Phase 2 立项前先在 Phase 1 数据上量化预算 |
| D 的 2× 参数显存 | Phase 3 评估时与 FSDP / activation swap 联合考虑 |
CombinePartialResult 的内存开销(持有 unpermute 中间状态) |
中间状态大小与 token 数线性相关,与 dispatch 阶段保存的 permuted_indices 相当,可接受 |
7. 验收标准
子方向 A(本期)
-
platform.differentiable_all_to_all_single支持async_op=True,PyTorch 和 NPU 路径均实现; -
AllToAllTokenDispatcher提供combine_start/combine_wait接口; -
MoE.forward按新时序执行,shared_expert 与 combine 异步重叠; - OV-01~OV-04 通过;OV-D01 数值正确;
- 无 shared_expert 时同步退化,现有 ST 无回归。
子方向 B(Phase 1)
-
OverlapExpertParallel/CommComputeOverlap从 example 移入hyper_parallel/core/expert_parallel/; - 状态完全脱离 EP 实例,通过
DispatchMetadata携带; - MindSpore 路径完成;
- OV-B01~OV-B06 全部通过;
- 至少一个 PP + EP + FSDP 组合的端到端 ST 加入 CI。
子方向 C(Phase 2)
- 自定义 GEMM autograd(Torch)落地;
-
DeferredWQueue与 scheduler 集成,cooldown drain 正确; - 端到端 step 时延相对 Phase 1 下降不少于设定阈值(设计文档中明确);
- 激活显存上升幅度落在预算内。
子方向 D(评估期)
- 用户场景 / 模型规模明确(
pp_size ≥ 16的真实需求); - 双向 pipeline scheduler 设计文档评审通过;
- CUDA / NPU profiler 验证气泡下降至
(P/2 - 1) × (F + B - 2W)量级。
8. 参考
- HyperParallel:
hyper_parallel/platform/torch/common/moe.py—MoE.forward(shared_expert 当前串行位置); - HyperParallel:
hyper_parallel/core/expert_parallel/expert_parallel.py—ExpertParallel._token_dispatch、_token_combine; - HyperParallel:
hyper_parallel/platform/platform.py—differentiable_all_to_all_single平台接口; - HyperParallel:
hyper_parallel/core/pipeline_parallel/— Pipeline scheduler、CommComputeOverlap、ScheduleInterleaved1F1B; - HyperParallel:
examples/torch/pp_overlap/pp_overlap_moe_example.py— B 子方向参考实现; - HyperParallel:
docs/expert_parallel.md; - DeepSeek-V3 Technical Report — DualPipe 调度与 W/D 拆分原始描述(D 子方向背景)。
schema_version: 1
source: gitcode
gitcode_repo: mindspore/hyper-parallel
gitcode_issue: 110
source_url: https://gitcode.com/mindspore/hyper-parallel/issues/110
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with platform/platform.py and the existing examples/torch/pp_overlap/pp_overlap_moe_example.py, then trace AllToAllTokenDispatcher.combine and MoE.forward. Done means the scoped A work supports an async all-to-all handle, separates combine_start/combine_wait, overlaps shared_expert computation, and preserves the synchronous no-shared-expert path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, pytorch
- Domain
- distributed-systems, performance
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100