mindspore-ai / mindspore-ai/hyper-parallel
task: hyper_parallel.fully_shard兼容接口泛化能力提升
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 53
- Forks
- 63
- Avg merge
- 23h 45m
- Merged PRs (30d)
- 63
Description
HyperParallel FSDP 测试方案
版本:v1.1 | 范围:
fully_shardAPI + HSDPModule 接口
Level 1:HSDPModule 接口单点测试
原则:覆盖 fully_shard() 函数入参 + HSDPModule 方法的覆盖 gap;语义相关接口合并到一个 case;2–4 卡;简单 MLP;目标是接口行为正确性,不做完整精度对标。
fully_shard() 入参 gap 分析
| 参数 | 当前覆盖状态 | Gap |
|---|---|---|
mesh=None |
已有(test_fully_shard_none_mesh) |
— |
mesh=DeviceMesh |
已有(多个用例) | — |
reshard_after_forward=True/False |
静态构造时已覆盖;动态 setter 未独立测试 | L1-01 补充 |
shard_placement_fn |
_test_hsdp_param 中有单元,但 fully_shard API 层未独立测试 |
L1-07 补充 |
mp_policy 全字段组合 |
严重不足:仅有 fp16/fp32/fp32 一种组合 |
L1-10~13 重点补充 |
offload_policy |
有 pin_memory=True 一种 |
— |
ignored_params |
无独立单点测试 | L1-06 补充 |
replicate_params |
有精度测试(1D/2D),行为语义已基本覆盖 | — |
comm_fusion |
有 ON/OFF 精度测试;无 ON vs OFF 数值一致性对比 | L1-08 补充 |
module=List[Module] |
有精度测试;HSDPModule 接口覆盖不完整 | L1-09 补充 |
HSDPModule 方法 gap 分析
| 方法 | 当前覆盖状态 | Gap |
|---|---|---|
set_requires_gradient_sync |
已有(test_fully_shard_module) |
— |
zero_grad |
未独立测试 | L1-04 补充 |
set_modules_to_forward_prefetch |
已有 | — |
set_modules_to_backward_prefetch |
已有 | — |
reshard() / unshard() |
HSDPParam 层有;API 层幂等性未测 | L1-05 补充 |
set_is_last_backward |
已有 | — |
set_requires_all_reduce |
未独立测试 | L1-02 补充 |
set_reshard_after_forward(动态) |
未独立测试 | L1-01 补充 |
set_reshard_after_backward(动态) |
未独立测试 | L1-01 补充 |
set_reduce_op_type |
未独立测试 | L1-03 补充 |
L1 用例列表
| # | 用例名 | 目标文件 | 卡数 | 核心断言 |
|---|---|---|---|---|
| L1-01 | test_dynamic_reshard_control |
_test_fully_shard_module.py |
2 | set_reshard_after_forward(False) → forward 后 param.data.numel()==full_numel;toggle 回 True → shard_numel;set_reshard_after_backward 同理;动态切换不抛异常 |
| L1-02 | test_set_requires_all_reduce |
_test_fully_shard_module.py |
4(2×2 HSDP) | 关闭时两 replica-group grad 不等;开启后 grad atol=1e-6 一致;recurse=False 只影响顶层 module |
| L1-03 | test_set_reduce_op_type |
_test_fully_shard_module.py |
2 | "sum" → grad == ref_grad × world_size;"avg" → grad == ref_grad;mid-train 切换不污染 optimizer state |
| L1-04 | test_zero_grad |
_test_fully_shard_module.py |
2 | N 步累积后调用 zero_grad():param.grad is None;param.data 与 snapshot 一致;后续 backward 产生新鲜 grad |
| L1-05 | test_manual_reshard_unshard_lifecycle |
_test_fully_shard_module.py |
2 | 幂等性(重复调用不报错);numel 正确(shard/full);async_op=True 时 handle wait 后方可读取 |
| L1-06 | test_ignored_params |
_test_fully_shard_precision.py |
2 | ignored 参数为普通 Tensor 非 DTensor;numel==full_numel;grad 不跨 rank 同步;其余参数正常 reduce-scatter |
| L1-07 | test_custom_shard_placement_fn |
_test_hsdp_param.py |
2 | dim-1 分片:param.shape[1]==full_shape[1]//world_size;loss + grad atol=1e-5 vs 单卡;Replicate() 返回时 shape == full_shape |
| L1-08 | test_comm_fusion_numerical_correctness |
_test_fully_shard_precision.py |
2 | abs(loss_fusion - loss_nofusion) < 1e-6;per-param grad atol=1e-6(comm_fusion 开/关数值等价性) |
| L1-09 | test_fully_shard_list_input |
_test_fully_shard_module.py |
2 | return 是 list,两元素均有 HSDPModule 接口;独立控制互不干扰;两者 grad 均有限 |
L1-10~13:混合精度策略充分校验(重点补强)
MixedPrecisionPolicy 有 5 个字段:param_dtype、reduce_dtype、output_dtype、cast_forward_inputs、apply_grad_on_fp32_main_grad。
当前仅覆盖了 fp16/fp32/fp32 一种组合,以下补强:
| # | 用例名 | mp_policy 配置 |
卡数 | 核心断言 |
|---|---|---|---|---|
| L1-10 | test_mp_bf16_param_fp32_reduce |
param_dtype=bf16, reduce_dtype=fp32, output_dtype=fp32 |
2 | 参数存储为 bf16;reduce 后 grad 为 fp32;loss + grad norm atol=1e-3 vs 单卡 bf16 参考 |
| L1-11 | test_mp_bf16_all_bf16 |
param_dtype=bf16, reduce_dtype=bf16, output_dtype=bf16 |
2 | 全程 bf16;output tensor dtype 为 bf16;grad dtype 为 bf16;loss atol=1e-3 |
| L1-12 | test_mp_cast_forward_inputs_false |
param_dtype=fp16, reduce_dtype=fp32, cast_forward_inputs=False |
2 | 输入不被 cast(forward hook 确认 input dtype 不变);loss finite;无 dtype 不匹配报错 |
| L1-13 | test_mp_apply_grad_on_fp32_main_grad |
param_dtype=fp16, reduce_dtype=fp32, apply_grad_on_fp32_main_grad=True |
2 | grad 累积到 fp32 main grad;param.grad dtype 为 fp32;精度 atol=1e-5 vs fp32 单卡参考 |
混合精度覆盖矩阵(补强后):
param_dtype |
reduce_dtype |
cast_forward_inputs |
apply_grad_on_fp32_main_grad |
覆盖用例 |
|---|---|---|---|---|
| None(fp32) | None | True | False | 已有 |
| fp16 | fp32 | True | False | 已有 |
| bf16 | fp32 | True | False | L1-10 |
| bf16 | bf16 | True | False | L1-11 |
| fp16 | fp32 | False | False | L1-12 |
| fp16 | fp32 | True | True | L1-13 |
目标文件:L1-10~13 均归入
tests/torch/fully_shard/_test_fully_shard_precision.py
Level 2:特性耦合测试
原则:简单网络(≤6 层);精度统一对标单卡/DDP;按特性命名归档文件。
L2 用例列表
| # | 用例名 | 目标文件 | 卡数 | 核心断言 |
|---|---|---|---|---|
| L2-01 | test_gradient_accumulation |
_test_fully_shard_precision.py |
2 | N micro-step 累积后 merged grad == large-batch DDP grad atol=1e-5;中间步 rank 间 grad 不等(确认未同步) |
| L2-02 | test_frozen_params_mixed_training |
_test_fully_shard_precision.py |
2 | frozen 参数 grad is None;data 不变;非 frozen 层 grad atol=1e-5 vs 单卡;FSDP 不为 frozen 参数发起 reduce-scatter |
| L2-03 | test_reentrant_ac_fsdp |
_test_fully_shard_with_ac.py |
2 | loss atol=1e-5;per-layer grad norm atol=1e-5;首/末层 grad tensor atol=1e-5 vs 单卡 |
| L2-04 | test_nonreentrant_ac_fsdp |
_test_fully_shard_with_ac.py |
2 | 同 L2-03;额外:峰值内存低于无 AC baseline |
| L2-05 | test_selective_ac_fsdp |
_test_fully_shard_with_ac.py |
2 | 同 L2-03;额外:checkpoint 层 forward-hook 触发 2次/backward,非 checkpoint 层 1次 |
| L2-06 | test_ac_activation_swap_fsdp |
_test_fully_shard_with_ac.py |
2 | loss atol=1e-5;grad norm atol=1e-5;swap 回 GPU 后无 device mismatch;recompute 时激活在 GPU 上 |
| L2-07 | test_grad_clip_with_dtensor_grads |
_test_fully_shard_precision.py |
2 | clip 后 global norm ≤ max_norm+1e-6;per-param grad atol=1e-5 vs 单卡;全局 norm 而非 per-shard norm |
| L2-08 | test_dynamic_sequence_length |
_test_fully_shard_precision.py |
2 | 连续 5 步不同 seq_len 无 hang(60s timeout);每步 loss finite;grad norm finite;param shape 不变 |
| L2-09 | test_pp_fsdp_coupling |
_test_fully_shard_with_pp.py |
4(2PP×2FSDP) | loss atol=1e-5 vs 4卡 DDP;stage boundary grad atol=1e-5;无死锁(60s timeout) |
| L2-10 | test_ep_fsdp_coupling |
_test_fully_shard_with_ep.py |
4(2EP×2FSDP) | loss atol=1e-4;per-expert grad norm atol=1e-4;无 NCCL 报错 |
L2 目标文件命名说明:
| 文件 | 归档用例 |
|---|---|
_test_fully_shard_precision.py(已有) |
L2-01、L2-02、L2-07、L2-08 |
_test_fully_shard_with_ac.py(新建) |
L2-03、L2-04、L2-05、L2-06 |
_test_fully_shard_with_pp.py(新建) |
L2-09 |
_test_fully_shard_with_ep.py(新建) |
L2-10 |
Level 3:真实网络结构测试
原则:
- 双校验(loss 标量 + global grad norm),两者须同时通过
- 至少跑 2 步(step0 + optimizer 更新后的 step1),验证 DTensor→optimizer 交接正确性
- 固定 seed,同进程同卡数重跑须 bitwise 一致,FSDP 下的不确定性是 blocking bug
- 每个网络结构须覆盖 1D-mesh(FSDP)和 2D-mesh(HSDP)vs DDP 的精度自洽性
L3 用例列表
| # | 用例名 | 目标文件 | 卡数 | 架构摘要 | 并行策略 |
|---|---|---|---|---|---|
| L3-01 | test_llm_decoder_hsdp_vs_ddp |
_test_fully_shard_with_llm.py |
4 | 4层 Transformer Decoder(RMSNorm+MHA+SwiGLU)+ Embedding + 权重共享输出层;vocab=1024, hidden=256, seq=128 | HSDP (replicate=2, shard=2) vs DDP |
| L3-02 | test_llm_decoder_fsdp_1d_vs_ddp |
_test_fully_shard_with_llm.py |
2 | 同 L3-01 架构 | FSDP 1D vs DDP |
| L3-03 | test_moe_llm_ep_fsdp_vs_ddp |
_test_fully_shard_with_llm.py |
4 | 4层 Decoder(2层标准FFN + 2层MoE:4 expert, top-2 routing, expert_dim=2×hidden);hidden=256, seq=64 | 3D mesh (replicate=1, fsdp=2, ep=2) vs 单卡 |
| L3-04 | test_vit_fsdp_vs_ddp |
_test_fully_shard_with_vit.py |
2 | patch embedding + 6 encoder block(LN+MHA+LN+MLP-GELU)+ CLS token + 分类头;hidden=256, img=224 | FSDP 1D vs DDP;patch embedding 和分类头不分片 |
| L3-05 | test_chunked_ce_fsdp_vs_ddp |
_test_fully_shard_with_llm.py |
2 | 2层 Decoder + 大 vocab 输出层(vocab=32768);CE 分 chunk_size=512 计算 | FSDP 1D vs DDP;per-chunk loss 一致性额外验证 |
| L3-06 | test_multimodal_deepstack_fsdp |
_test_fully_shard_with_vit.py |
2 | 4-block ViT(hidden=128)→ 2层 projection MLP → 2层 Decoder(hidden=256);两子模型独立 fully_shard |
FSDP 1D;projection MLP 不分片 |
各 L3 用例断言规格
L3-01 / L3-02(LLM 1D/2D-mesh vs DDP):
- step0 loss
atol=1e-5;step1 loss(optimizer 更新后)atol=1e-5 - global grad norm
atol=1e-5 - 首层 attention weight grad tensor
atol=1e-5 - 末层 FFN weight grad tensor
atol=1e-5
L3-03(MoE EP+FSDP vs 单卡):
- total loss
atol=1e-4;dense 层 grad normatol=1e-5;per-expert grad normatol=1e-4 - 无 all-to-all / all-gather 通信冲突(无 NCCL 报错)
L3-04(ViT FSDP vs DDP):
- loss
atol=1e-5;grad normatol=1e-5 - patch embedding grad(不分片):所有 rank bitwise 一致且等于 DDP 参考
- 末层 MLP weight grad
atol=1e-5
L3-05(Chunked CE FSDP vs DDP):
- total loss
atol=1e-5;per-chunk lossatol=1e-5;sum(per_chunk_losses) == total_loss(atol=1e-6,一致性验证) - grad norm
atol=1e-5;输出层 weight grad normatol=1e-5
L3-06(多模态 Deep Stack):
- E2E loss
atol=1e-5;ViT grad normatol=1e-5;Decoder grad normatol=1e-5 - projection MLP grad(不分片)
atol=1e-5 - 跨模块梯度流通验证:projection MLP grad ≠ 0(梯度未在模块边界断流)
L3 目标文件命名说明:
| 文件 | 归档用例 |
|---|---|
_test_fully_shard_with_llm.py(新建) |
L3-01、L3-02、L3-03、L3-05 |
_test_fully_shard_with_vit.py(新建) |
L3-04、L3-06 |
精度自洽矩阵
| 并行配置 | loss tol | grad norm tol | 覆盖用例 |
|---|---|---|---|
| FSDP 1D, fp32 | 1e-5 | 1e-5 | L1-03, L2-01, L3-02, L3-04, L3-05 |
| FSDP 1D, bf16 | 1e-3 | 1e-3 | L1-10, L1-11 |
| HSDP 2D, fp32 | 1e-5 | 1e-5 | L1-02, L3-01 |
| TP + FSDP, fp32 | 1e-5 | 1e-5 | 已有 TP+FSDP E2E 用例 |
| EP + FSDP, fp32 | 1e-4 | 1e-4 | L2-10, L3-03 |
| AC + FSDP, fp32 | 1e-5 | 1e-5 | L2-03, L2-04, L2-05 |
| AC + swap + FSDP, fp32 | 1e-5 | 1e-5 | L2-06 |
| PP + FSDP, fp32 | 1e-5 | 1e-5 | L2-09 |
精度自洽规则:
- baseline 锚点固定:baseline 固定为单卡 fp32 或等价 DDP,禁止 FSDP-vs-FSDP 互比
- 不允许静默放宽容忍度:若测试在
1e-5失败但1e-4通过,必须 triage 根因,说明存在数值累积 bug,不允许静默放宽 - 双指标独立通过:grad norm 通过 ≠ 精度正确——grad norm 通过但张量元素级比对失败,说明存在 norm-cancellation bug;两个指标须独立通过
- 2 步验证:Level 3 至少跑 2 步,验证 DTensor→optimizer 交接不断
- 确定性要求:Level 3 固定 seed,同进程同卡数重跑须 bitwise 一致;FSDP 下的不确定性是 blocking bug
关键文件映射
| 角色 | 路径 |
|---|---|
| 核心 API | hyper_parallel/core/fully_shard/api.py |
| MixedPrecisionPolicy | hyper_parallel/core/fully_shard/utils.py |
| Torch 调度器 | hyper_parallel/platform/torch/fully_shard/ |
| 现有接口测试(扩充 L1-01~05, L1-09) | tests/torch/fully_shard/_test_fully_shard_module.py |
| 现有精度测试(扩充 L1-06, L1-08, L1-10 |
tests/torch/fully_shard/_test_fully_shard_precision.py |
| 现有参数单元(扩充 L1-07) | tests/torch/fully_shard/_test_hsdp_param.py |
| AC 耦合(新建,L2-03~06) | tests/torch/fully_shard/_test_fully_shard_with_ac.py |
| PP 耦合(新建,L2-09) | tests/torch/fully_shard/_test_fully_shard_with_pp.py |
| EP 耦合(新建,L2-10) | tests/torch/fully_shard/_test_fully_shard_with_ep.py |
| LLM 场景(新建,L3-01~03, L3-05) | tests/torch/fully_shard/_test_fully_shard_with_llm.py |
| ViT/多模态场景(新建,L3-04, L3-06) | tests/torch/fully_shard/_test_fully_shard_with_vit.py |
schema_version: 1
source: gitcode
gitcode_repo: mindspore/hyper-parallel
gitcode_issue: 35
source_url: https://gitcode.com/mindspore/hyper-parallel/issues/35
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 by reading hyper_parallel/core/fully_shard/api.py and utils.py, then run the existing tests under tests/torch/fully_shard/. Extend the named module, precision, and parameter test files, and add the specified AC, PP, EP, LLM, and ViT test files. Done means the listed L1–L3 cases pass with their stated accuracy, gradient, determinism, and timeout checks.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, pytorch
- Domain
- distributed-systems, testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 32/100