mindspore-ai / mindspore-ai/hyper-parallel

[Benchmark] Qwen3-8B-lite fully_shard 性能对比(torch_npu 原生 vs hyper torch/ms)

Open
#705 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

Qwen3-8B-lite fully_shard 性能优化实验全记录

Issue 类型:Benchmark + Profiler 瓶颈分析 + 源码优化验证
测试目录dev/test/qwen3_8b_hsdp2/
环境:Ascend NPU 8 卡,CANN 9.0,seq_len=4096,batch=1,steps=20/warmup=2
最后更新:2026-06-08(含 P12 norm/lm_head 拆 wrap 负向验证)


零、执行摘要

维度 结论
最优配置 hyper torch + prefetch(1/1) + PR707 → 542 ms/step(FSDP8)
vs 原生 3.7%(原生 563 ms);HSDP24 prefetch 后 持平(790 vs 791 ms)
根因 hyper 默认慢 不在计算(Computing 反而快 47 ms),在 通信重叠率低(4.6% vs 82.6%)+ per-param collective 碎片化(360 AG vs 38)
关键开关 prefetch 是质变(-17%);comm_fusion 单独开更慢;P0/P1 让 cf+prefetch 追平原生
残余热点 post_backward:norm(~190 ms,不宜拆 wrap)、pre_backward prefetch:layers.7(~107 ms)

性能演进(FSDP8 hyper torch,ms/step)

默认 658 ──prefetch──► 544 ──PR707──► 542  ⭐ 当前最优
         │
         └──comm_fusion 单独──► 701(更慢)
         └──cf+prefetch──► 581 ──P0──► 568 ──P1──► 565 ≈ 原生 563

一、测试方法与配置

1.1 对比路径
标识 后端 说明
原生 torch_npu.distributed.fsdp.fully_shard NPU 原生 FSDP2
hyper torch hyper_parallel + HYPER_PARALLEL_PLATFORM=torch 本 Issue 主要优化对象
hyper MS hyper_parallel + MindSpore 后端 参考对比
1.2 统一参数
模型 Qwen3-8B-lite:dim=4096,layers=8,ffn=12288,32 heads / 8 kv
Mesh FSDP8 (8,) / HSDP24 (2,4)
精度 bf16 param + fp32 reduce
优化器 AdamW(lr=1e-4),weight_decay=0
对齐 align_data_8b/init_weights.pt + preset_batches.pt,seed=42
计时 warmup 后整步 torch.npu.synchronize() 平均
1.3 Profiler 采集
  • torch_npu.profiler,Level0,with_stack=False
  • schedule(wait=2, warmup=1, active=2, repeat=1) → 分析 rank0 step 3–4
  • 数据源:ASCEND_PROFILER_OUTPUT/step_trace_time.csv + operator_details.csv
1.4 开关说明
开关 含义
prefetch 正反向各预取 1 层(set_modules_to_forward/backward_prefetch
comm_fusion 模块级 fused AG/RS(collective 次数 360→38)
P0/P1 本地 hyper_parallel/platform/torch/fully_shard/ 源码优化
PR707 hsdp_scheduler.py:hook 顺序 unshard → prefetchPR #707

二、实验全景(11 项 e2e + 11 项 profiler)

2.1 端到端实验(无 Profiler,steps=20)
ID 实验 Mesh ms/step vs 原生 结果文件
T1 原生 默认 FSDP8 563.08 baseline_8card/torch_native_8b_8card_fsdp_s4096.json
T2 hyper 默认 FSDP8 657.88 +17% pure_fsdp2_8card/hyper_torch_8b_8card_fsdp_s4096.json
T3 hyper MS 默认 FSDP8 698.16 +24% pure_fsdp2_8card/mindspore_8b_8card_fsdp_s4096.json
T4 hyper +prefetch FSDP8 543.59 -3.5% hyper_torch_prefetch/..._prefetch.json
T5 hyper +prefetch PR707 FSDP8 542.23 -3.7% pr707_hyper_torch_prefetch/..._pr707.json
T6 hyper +comm_fusion FSDP8 700.80 +24% hyper_torch_comm_fusion/..._comm_fusion.json
T7 原生 默认 HSDP24 791.28 torch_native_hsdp24/..._foreach_false.json
T8 hyper 默认 HSDP24 1028.15 +30% baseline_8card/torch_align_..._hsdp24.json
T9 hyper MS 默认 HSDP24 1051.14 +33% baseline_8card/mindspore_align_..._hsdp24.json
T10 hyper +prefetch HSDP24 789.67 -0.2% hyper_torch_prefetch/..._hsdp24_prefetch.json
T11 hyper +comm_fusion HSDP24 1100.49 +39% hyper_torch_comm_fusion/..._hsdp24_comm_fusion.json
2.2 Profiler 实验(steps=8,含 profiler 开销)
ID 实验 prof e2e Stage Compute Comm未重叠 重叠率 AG/RS 目录
P1 原生 FSDP8 566.50 566.8 521.8 40.7 82.6% 38/40 profiler/torch_native_fsdp8/
P2 hyper 无 prefetch 660.46 662.9 474.7 181.5 4.6% 360/364 profiler/hyper_torch_fsdp8/
P3 hyper +prefetch 546.03 549.5 492.4 50.2 80.1% 360/364 profiler/hyper_torch_fsdp_prefetch/
P4 hyper +prefetch PR707 544.70 551.5 492.9 51.7 79.8% 360/364 profiler/hyper_torch_fsdp_prefetch_pr707/
P5 hyper +prefetch fwd1/bwd2 544.56 551.0 491.7 52.0 80.0% 360/364 profiler/hyper_torch_fsdp_prefetch_fwd1_bwd2/
P12 split norm/lm_head 570.71 574.7 486.6 82.7 66.0% 360/364 profiler/hyper_torch_fsdp_prefetch_split_norm_lm_head/
P6 cf+prefetch 优化前 581.05 584.5 532.0 46.7 81.2% 38/40 profiler/..._comm_fusion_prefetch/
P7 cf+prefetch P0 568.45 570.6 519.3 44.3 81.5% 38/40 profiler/..._prefetch_p0/
P8 cf+prefetch P1 565.31 567.5 515.1 46.8 80.5% 38/40 profiler/..._prefetch_p1/
P9 原生 HSDP24 792.41 798.6 626.1 165.6 71.0% 38/40 profiler/torch_native_hsdp24/
P10 hyper 无 prefetch 1025.78 1028.9 515.6 505.4 32.3% 360/364 profiler/hyper_torch_hsdp24/
P11 hyper +prefetch 793.15 801.0 570.3 224.2 62.9% 360/364 profiler/hyper_torch_hsdp24_prefetch/

三、优化过程(按阶段)

阶段 0:基线对比(T1/T2/T7/T8)

发现:hyper 默认比原生慢 17%(FSDP8)/ 30%(HSDP24),但 loss 完全对齐。

Mesh 原生 hyper 默认 差距
FSDP8 563 ms 658 ms +95 ms
HSDP24 791 ms 1028 ms +237 ms
阶段 1:Profiler 根因定位(P1/P2/P9/P10)

假设:hyper 计算慢?→ 否定

FSDP8 rank0 分解(step 3–4):

指标 原生 P1 hyper 无 prefetch P2 Δ
Stage 566.8 ms 662.9 ms +96 ms
Computing 521.8 ms 474.7 ms -47 ms
Comm(未重叠) 40.7 ms 181.5 ms +141 ms
Comm(已重叠) 193.6 ms 8.7 ms -185 ms
重叠率 82.6% 4.6%
collective 38 AG / 40 RS 360 AG / 364 RS 9× 碎片化
Stage 差距 +96 ms ≈ Computing -47 ms + Comm(未重叠) +141 ms

HSDP24 同理:hyper Computing 515.6 ms < 原生 626.1 ms,但 Comm(未重叠) 505.4 ms >> 原生 165.6 ms。

根因闭环:逐参数 collective + 无 prefetch → 通信几乎不与计算重叠。

阶段 2:开启 prefetch(T4/T10,P3/P11)

措施train_hyper_torch.py 增加 --prefetch,正反向各 1 层。

Mesh 无 prefetch +prefetch 变化 重叠率
FSDP8 e2e 658 ms 544 ms -17% 4.6%→80.1%
HSDP24 e2e 1028 ms 790 ms -23% 32.3%→62.9%

prefetch 是质变级优化:FSDP8 超越原生,HSDP24 追平。

阶段 3:comm_fusion 路径优化(P6→P7→P8,P0/P1 源码)

背景comm_fusion 单独开启更慢(T6: 701 ms);但 collective 次数与原生对齐(38/40),适合大模型。

P0 措施state.py, param_group.py):

  • post_backward_for_comm_fusion() 流水线重排:先 issue 当前层 RS,再 drain 上一层
  • 每层 _reduce_scatter_handle 独立存储
  • reduce_scatter_copy_in()torch.cat + 单次 copy
  • ensure_flat_param_buffer() 延迟初始化

P1 措施param_group.py, param.py, state.py):

  • foreach_all_gather_copy_out() AG view 零拷贝
  • release_unshard_buffers()shard() 时释放
  • _reduce_scatter_input 跨 step 复用
阶段 prof e2e vs 优化前 关键算子变化
cf+prefetch 优化前 P6 581.05 ms split_with_sizes_copy 45.6 ms
P0 P7 568.45 ms -12.6 ms aten::copy_ 153→115 ms
P1 P8 565.31 ms -3.1 ms split_with_sizes_copy →0 ms
原生 P1 566.50 ms 参考
prefetch only P3 546.03 ms 仍最快
阶段 4:调度微调(P4/P5,PR707 + prefetch 深度)

PR #707hsdp_scheduler.py forward/backward pre-hook 从 prefetch→unshard 改为 unshard→prefetch

指标 P3 旧顺序 P4 PR707 Δ
e2e(无 profiler) 543.59 ms 542.23 ms -1.36 ms
prof e2e 546.03 ms 544.70 ms -1.33 ms
unshard:tok_embeddings device 38.7 ms 35.8 ms -2.9 ms
prefetch:layers.7 device 107.2 ms 107.5 ms 不变

prefetch 深度扫描 P5(fwd=1, bwd=2):

配置 prof e2e 重叠率
fwd1/bwd1 P3 546.03 ms 80.1%
fwd1/bwd2 P5 544.56 ms 80.0%

加深 prefetch 无收益(差 0.3%,噪声内)。

阶段 5:norm/lm_head 拆 wrap 验证(P12)❌ 负向结果

假设post_backward:norm(~186 ms)因 norm 与 lm_head 绑在同一 FSDP 单元,RS 粒度过粗;拆分后可降低尾部 RS 耗时。

措施train_hyper_torch.py 新增 --split-norm-lm-head,将

fully_shard([norm, lm_head])  # 默认

改为

fully_shard(norm); fully_shard(lm_head)  # 各自独立 wrap

配置:FSDP8 + prefetch + PR707,其余与 P4 相同。

指标 P4 绑定 norm+lm_head P12 拆分 Δ
prof e2e 544.70 ms 570.71 ms +26.0 ms(慢 4.8%)
Stage 551.5 574.7 +23.2
Comm(未重叠) 51.7 82.7 +31.0
重叠率 79.8% 66.0% -13.8 pp
AG/RS 次数 360/364 360/364 不变

Hook 变化(device ms,rank0,2 step)

Hook P4 绑定 P12 拆分
post_backward:norm 185.6 47.6
post_backward:lm_head (含在 norm 内) 278.5
norm + lm_head 合计 ~186 ~326
post_backward:layers.7 19.8 75.8

根因

  1. 绑定时 norm+lm_head 一次 RS(~186 ms),可与计算较好重叠
  2. 拆分后变成 两次串行 RS(48 + 279 ms),合计更高且更难重叠
  3. wrap 单元 11→12,prefetch 链被打断,layers.7 post_backward 从 20→76 ms
  4. lm_head 参数量远大于 norm,不应单独拆出,绑定反而更优

结论:❌ 保持默认 fully_shard([norm, lm_head]),不要拆分。


四、Profiler 深度分析

4.1 FSDP8 配置横向对比(rank0)
配置 Stage Compute Comm未重叠 Comm未重叠占Stage 重叠率
原生 566.8 521.8 40.7 7.2% 82.6%
hyper 无 prefetch 662.9 474.7 181.5 27.4% 4.6%
+prefetch 549.5 492.4 50.2 9.1% 80.1%
+prefetch PR707 551.5 492.9 51.7 9.4% 79.8%
cf+prefetch P1 567.5 515.1 46.8 8.2% 80.5%
4.2 HSDP24 配置横向对比(rank0)
配置 Stage Compute Comm未重叠 重叠率
原生 798.6 626.1 165.6 71.0%
hyper 无 prefetch 1028.9 515.6 505.4 32.3%
+prefetch 801.0 570.3 224.2 62.9%

HSDP prefetch 后 Comm(未重叠) 仍高于原生(224 vs 166 ms),是 HSDP 残余差距来源。

4.3 Hook 热点(device 累计 ms,2 step,rank0)
Hook 无 prefetch P2 +prefetch P3 PR707 P4 split P12 cf+P1 P8
post_backward:norm 280 185 186 48 190
post_backward:lm_head 279
pre_backward prefetch:layers.7 107 108 108 114
post_backward:layers.7 ~80 ~20 20 76
post_backward:layers.*(其他层) ~80 ~60 ~61 ~60 ~65
HSDP post_backward:layers.7 707 521

解读

  • prefetch 将 norm RS 从 280→185 ms;profiler 记为 post_backward:norm 实为 norm+lm_head 绑定单元的一次 RS
  • 拆分 norm/lm_head(P12)反而更慢:两次 RS 合计 ~326 ms,重叠率降至 66%
  • layers.7 backward prefetch AG 是固定尾部开销(~107 ms)
  • HSDP 无 prefetch 时 layers.7 post_backward 极高(707 ms),prefetch 后大幅缓解

五、结论与配置推荐

5.1 核心结论
  1. mesh:纯 FSDP8 比 HSDP24 快 ~1.4×,公平对比优先 FSDP8。
  2. prefetch 必开:默认配置不可用(慢 17–30%);开启后 FSDP8 超原生。
  3. comm_fusion 单独开有害;配合 P0/P1 + prefetch 可与原生持平,但不如 prefetch-only 快。
  4. PR707 建议合入:小幅收益(~1.3 ms),首层 unshard 阻塞减少。
  5. prefetch 深度 1/1 足够;norm/lm_head 保持绑定 wrap(拆分实测慢 4.8%);HSDP replicate AR 待优化。
5.2 配置推荐
场景 推荐 预期 ms/step
FSDP8 极致性能 prefetch=True, comm_fusion=False(+PR707) ~542
对齐原生 collective 次数 / 大模型 prefetch=True, comm_fusion=True(P0/P1) ~565
HSDP24 追平原生 prefetch=True ~790
❌ 不推荐 默认无 prefetch / 单独 comm_fusion / split norm+lm_head 658–1100 / 571

六、复现命令

source ~/env.sh
cd dev/test/qwen3_8b_hsdp2

# ── 端到端 ──
./run_baseline_8card.sh          # T1/T8 等基线
./run_pure_fsdp2_8card.sh        # T2/T3 hyper 默认
./run_hyper_torch_prefetch.sh    # T4/T10 +prefetch
./run_hyper_torch_comm_fusion.sh # T6/T11 comm_fusion

# ── PR707 验证(本地 hyper-parallel 已 apply patch)──
python train_hyper_torch.py --nproc 8 --mesh fsdp --prefetch --prefetch-layers 1 \
  --align-dir align_data_8b --steps 20 \
  --output-json results/pr707_hyper_torch_prefetch/out.json

# ── Profiler ──
./run_torch_native_fsdp8_profile.sh       # P1
./run_hyper_torch_fsdp8_profile.sh        # P2(若脚本存在)
./run_hyper_torch_prefetch_profile.sh fsdp  # P3
./run_hyper_torch_comm_fusion_prefetch_profile.sh fsdp  # P6/P7/P8
./run_torch_native_hsdp24_profile.sh    # P9
./run_hyper_torch_hsdp24_profile.sh     # P10/P11

# ── prefetch 深度扫描 ──
python train_hyper_torch.py --nproc 8 --mesh fsdp --prefetch \
  --prefetch-forward-layers 1 --prefetch-backward-layers 2 \
  --npu-profiler --profiler-dir results/profiler/hyper_torch_fsdp_prefetch_fwd1_bwd2 ...

七、结果文件索引

results/
├── baseline_8card/              # T1 原生 FSDP8, T8 hyper HSDP24
├── pure_fsdp2_8card/            # T2/T3 hyper 默认 FSDP8
├── hyper_torch_prefetch/        # T4/T10 +prefetch e2e
├── pr707_hyper_torch_prefetch/  # T5 PR707 e2e
├── hyper_torch_comm_fusion/     # T6/T11 comm_fusion e2e
├── torch_native_hsdp24/         # T7 原生 HSDP24
└── profiler/
    ├── torch_native_fsdp8/              # P1
    ├── hyper_torch_fsdp8/               # P2
    ├── hyper_torch_fsdp_prefetch/        # P3
    ├── hyper_torch_fsdp_prefetch_pr707/  # P4
    ├── hyper_torch_fsdp_prefetch_fwd1_bwd2/  # P5
    ├── hyper_torch_fsdp_prefetch_split_norm_lm_head/  # P12 ❌
    ├── hyper_torch_fsdp_comm_fusion_prefetch/     # P6
    ├── hyper_torch_fsdp_comm_fusion_prefetch_p0/  # P7
    ├── hyper_torch_fsdp_comm_fusion_prefetch_p1/  # P8
    ├── torch_native_hsdp24/              # P9
    ├── hyper_torch_hsdp24/               # P10
    └── hyper_torch_hsdp24_prefetch/      # P11

八、后续 TODO

  • 基线 e2e 对比(T1–T11)
  • Profiler 根因分析(P1/P2/P9/P10)
  • prefetch 验证(T4/T10,P3/P11)
  • comm_fusion 单独开启验证(T6/T11)
  • cf+prefetch P0/P1 源码优化(P6→P8)
  • PR #707 本地验证(T5/P4)
  • prefetch 深度扫描 fwd1/bwd2(P5)
  • 合入 PR #707 到上游 master
  • hyper torch 默认开启 prefetch
  • P2 norm/lm_head 拆 wrap 验证(P12) — ❌ 负向,慢 26 ms,保持绑定
  • P2 RS pack 改用 _chunk_cat(降 aten::copy_
  • HSDP replicate 维 AR 优化(P11 Comm未重叠 224 vs P9 166 ms)
  • hyper mindspore 同步 P0/P1 并 benchmark

本文档由 dev/test/qwen3_8b_hsdp2/ 全部实验数据自动汇总生成。

schema_version: 1
source: gitcode
gitcode_repo: mindspore/hyper-parallel
gitcode_issue: 192
source_url: https://gitcode.com/mindspore/hyper-parallel/issues/192

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 in dev/test/qwen3_8b_hsdp2/ with train_hyper_torch.py and the listed benchmark and profiler scripts. Reproduce the prefetch and comm_fusion configurations using the aligned data, then inspect the profiler output directories and compare step time, communication overlap, and collective counts. Done means the reported performance conclusions are reproducible and any source optimization is validated against the stated baselines.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, pytorch
Domain
distributed-systems, performance
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.