mindspore-ai / mindspore-ai/hyper-parallel

【RFC】EP 通算掩盖:共享专家重叠、DualPipe 与 W/D 掩盖

Open
#745 0 comments 0 reactions 0 assignees View on GitHub

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_bwddispatch_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_expertcombine all-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 立项需要改的面)

  1. 自定义 GEMM autograd:在 expert / attn_qkv / attn_proj / ffn 关键 GEMM 上提供 backward_d_only(grad_out, weight) → grad_inbackward_w_only(grad_out, input_saved) → grad_w 两个独立入口,绕开标准 autograd 的「原子 backward」假设。
  2. deferred W 队列:挂在 pipeline scheduler 上,per-rank 一个;条目包含 (grad_out_ref, input_saved_ref, weight_ref, target_grad_buffer)
  3. MoE / Attention / FFN 协作:backward 不再调用整块算子,而是按 D-only 调用 + 把 W 任务推入队列。
  4. flush 时机:在 OVERLAP_B_F 复合步的 a2a 等待窗口里调度 W 任务;在 1F1B cooldown 阶段统一 drain 剩余 W。
  5. 激活生命周期: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 和反向流的 stage 2P - 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.forwardcombine_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_expertshared_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 产品化要补

  1. 状态去实例化:现有 OverlapExpertParallel 仍把 _input_splits / _output_splits / _input_shape / _permuted_indices 写在自身上,跨 microbatch 不安全;改为通过 DispatchMetadata 显式回传给 combine,与 4.2 的 CombinePartialResult 统一。
  2. is_last_layer 自动推断:例子里靠用户手动传,产品化要让框架从 chunk 结构自动判定。
  3. MindSpore 路径:example 只跑了 Torch + NPU,需要补 MindSpore differentiable_all_to_all_single_async 与多线程协调器。
  4. 错误恢复: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_startx_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.pyMoE.forward(shared_expert 当前串行位置);
  • HyperParallel:hyper_parallel/core/expert_parallel/expert_parallel.pyExpertParallel._token_dispatch_token_combine
  • HyperParallel:hyper_parallel/platform/platform.pydifferentiable_all_to_all_single 平台接口;
  • HyperParallel:hyper_parallel/core/pipeline_parallel/ — Pipeline scheduler、CommComputeOverlapScheduleInterleaved1F1B
  • 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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.