已关闭
[RFC] Graph Mode(hyper_parallel/compile)设计方案 #414
mindspore-ci-bot创建于 9月20日关闭于 9月20日
9月20日 修改了issue 的描述
9月20日 关闭了 issue
mindspore-ci-bot
9月20日 评论:
9月20日 评论:
GitHub issue mindspore-ai/hyper-parallel#152 was closed.


9月20日 issue状态由 TODO 改变为 DONE
GitHub issue mindspore-ai/hyper-parallel#152 was closed.


0. 背景
Graph Mode 是与 eager 并行路径(
fully_shard/tensor_parallel/pipeline_parallel)互补的第二条接入方式:不采用 module wrapper,而是把整个训练步(forward + backward)
捕获成一张 joint FX graph,在图上完成并行切分与通信优化,再以单图执行。
用户只写模型代码 + 并行配置,框架负责:图捕获 → 并行分区 → 通信计算重叠 → 执行。
当前覆盖 FSDP(含与 automodel TP 的混合接入);TP/PP/EP 的图内 pass 为后续演进项。
1. 目标
PassPlan以 FQN / 通配 pattern 标记分片模块,无侵入式 wrap,用户不改模型代码。
torch.no_grad()下执行,消除 autograd 图维护开销与中间值保活。
model.parameters()即本地分片,optimizer / trainer 无 FSDP 感知。wait_tensor,与独立计算重叠。PassConfig驱动,pass 可插拔、可扩展。2. 设计边界
Graph Mode 负责:
GraphPass抽象与PassPipeline编排;wait_tensor下沉调度);PassConfig/PassPlan配置模型与 YAML 解析;GraphTrainer:懒编译、训练循环、梯度累积、optimizer step;MeshContext的 TP+FSDP 混合接入(TP 组复用、fsdp 子组注册)。Graph Mode 不负责:
MeshContext或init_device_mesh);3. 目录和文件清单
3.1 compile 包文件树
3.2 非 compile 接入文件
3.3 文档文件
4. 配置模型
Graph Mode 不引入第二份独立配置体系:配置只来自
PassConfig+PassPlan。两者均为纯数据类(torch-free),可独立于运行时导入与序列化。
4.1 PassConfig
enable_overlapTrueAutoOverlapPass移动wait_tensorfsdp_enabledTrueFSDPPass;置False用于纯 TP/PP 图模式。分布式未初始化或world_size == 1时FSDPPass自身早退fsdp_degreeNoneNone表示运行期回填:外部 Mesh 场景由GraphTrainer从子 mesh 回填,纯 FSDP 场景回退world_sizetp_size1sequence_parallelFalseloss_parallelFalsevalidate()校验tp_size >= 1、fsdp_degree为None或正整数。fsdp_enabled不探测torch.distributed(分布式初始化判断在FSDPPass.run内),保持配置类 torch-free。
4.2 PassPlan 与 YAML
fsdp_modules(exact FQN)+fsdp_patterns(fnmatch通配)。查询时 exact 优先,pattern 按插入序取首个匹配。
merge():合并两个 plan,key 冲突时other胜,不原地修改。create_sharding_plan_from_yaml):fsdp: enabled: true # 缺省时:modules / patterns 非空即视为 enabled modules: - name: tok_embeddings patterns: - pattern: "layers.*"仅
name/pattern被解析消费。历史示例中的reshard_after_forward/use_cpu_offload等字段已随死配置面移除,parser 不读取;待真实 reshard /offload pass 落地时再带消费方加回。
5. 编译流程
编译由
GraphTrainer驱动,首个 batch 懒触发(也可显式调用compile()):pass 流水线固定顺序:
FSDPPass仅在fsdp_enabled时加入,AutoOverlapPass仅在enable_overlap时加入。后端编译槽位(inductor 类后端)刻意预留未接线。
5.1 Device mesh 初始化(双模式)
fsdp_non_moe_mesh的fsdp_shard维(或device_mesh的dp维)子组,以
_register_process_group("fsdp", pg)注册,并回填fsdp_degree。TP+FSDP 混合时 FSDP 组是全世界的真子组,不能用
world_size,否则会沿 TP轴过度分片。
init_device_mesh构建一维("fsdp",)全 world mesh(纯 FSDP 路径)。5.2 梯度映射与累积
state_fqns序输出梯度(共享参数按 FQN 重复出现);_accumulate_grads按 FQN 对齐到 live model 参数,数量不一致时直接报错拒绝赋值,防止
zip静默截断。train_step可先跑后optimizer_step(以
zero_grad收尾)。FSDPPass早退,退化为纯图模式(图捕获与执行照常,无分片)。
6. 图捕获(tracer)
设计参考 torchtitan 的
experiments/graph_trainer/minimal_fx_tracer:torch.nn.utils.stateless._reparametrize_module从 live model 抽出为 flattensors,作为图的 leading placeholders(而非
get_attr节点)。图内因此无参数
get_attr节点,pass 可通过 reshape placeholder 切分图。torch.autograd.grad(loss, params)。为使其可被追踪,需要:
torch.compiler._patch_engine_backward(torchtitanpatched torch 提供;stock torch 缺失时
RuntimeWarning降级);torch.autograd.set_multithreading_enabled(False),否则 C++ autograd 引擎将 backward 派发到 worker 线程并以全新
contextvars.Context运行,tracing context 丢失。FakeTensorMode(allow_non_fake_inputs=True)+ 非 stricttracing +
preserve_node_meta()+_skip_nested_compile()(dynamo 内联torch.compile包装的函数,如 compiled attention kernel)。Tensor / int / float / bool / str / None。其余(callable、自定义对象)必须在
train_fn闭包内捕获,或注册为 pytree 节点。torch.no_grad()执行——图内已含显式 backward ops,再叠加 autograd 图会通过
grad_fn引用保活全部前向中间值。make_fx的record_stack_traces/record_module_stackkwargs 按版本探测转发;fwd→bwd 元数据拷贝容忍缺失stack_trace。GraphModule附带state_fqns/state_is_param,供梯度映射;state_is_param缺失(旧 trace)时降级为仅参数、跳过 buffer,而非抛错。7. FSDP 分区 pass
全部并行逻辑集中在 pass 内,trainer 只喂
model.parameters():PassPlan识别 FSDP 参数 placeholder(exact 优先,pattern 插入序首个匹配;plan 为
None时全量分片)。all_gather(Shard → Replicate):计算主体使用全量参数,图输入保持分片。
reduce_scatter(Replicate → Shard);非 FSDP 参数的梯度保持 full。
model.parameters()即本地分片,optimizer / trainer 无 FSDP 感知。组解析:按注册名
"fsdp"解析 process group;fsdp_degree从pass_config.fsdp_degree读取,缺省回退world_size。约束:各参数 dim 0 必须能被
fsdp_degree整除。8. 通信-计算重叠 pass
FSDPPass插入通信时wait_tensor紧跟通信 op(保证正确性)。AutoOverlapPass的目标:把每个wait_tensor下沉到其首个使用者之前,使通信与独立计算重叠。
_find_wait_nodes已完成wait_tensor节点识别;_move_wait_later为占位 no-op,调度器落地时替换该函数即可,pipeline 结构不变。
PassPipeline中预留,待后端集成落地时加入。
9. TP / SP 混合接入
(automodel 路径)烘焙完成,boundary forward 直接持有组对象。
graph-mode 只负责 FSDP 维。
GraphTrainer接收mesh_context后:mesh_context.fsdp_non_moe_mesh(缺省回退device_mesh);fsdp_shard维(automodel)或dp维(cp=1 场景);"fsdp"组并回填fsdp_degree。device_mesh["tp"]与fsdp_non_moe_mesh["tp"]的 rank 组与本地 rank 一致性校验。
PassConfig.tp_size/sequence_parallel/loss_parallel为信息字段:本阶段不驱动图内 pass,保留给未来 TP-aware pass。
10. 训练接入点
GraphTrainer( model, # nn.Module train_fn, # (model, input, label) -> loss pass_config, # PassConfig pass_plan=None, # PassPlan(声明式分片) optimizer_config=None, # {"lr": ..., "grad_clip": ...} device=None, # 缺省探测 npu -> cpu mesh_context=None, # automodel MeshContext(TP+FSDP 混合) )train(dataloader, max_steps=None, log_interval=None, log_fn=None)。每个 batch 移至
self.device,随后train_step(懒编译)+optimizer_step。set_pytree_pre_hook(hook):编译前注册模型特定 pytree(如 flex-attention
BlockMask);to(device):模型与后续 batch 落位。GraphTrainer独立于BaseTrainer/ eager FSDP;TP 已分片的模型可经
mesh_context注入,graph-mode 只补 FSDP 维。lr/grad_clip来自optimizer_config),建立于分片后参数之上。
11. 运行环境要求
torch.compiler._patch_engine_backward(torchtitan patched torch 或较新版本)。stock torch 会
RuntimeWarning,且
autograd.grad的 joint capture 可能不正确。torch.distributed;world_size == 1或未初始化时
FSDPPass早退(纯图模式)。FSDP 组大小需整除各参数 dim 0。device缺省探测npu(torch.npu.is_available())→cpu;mesh
device_type同规则。torch_npu已安装但无 NPU 时,Adam 的 foreach/fused 内核选择会探测
torch_npu.npu.current_device()并触发_lazy_init失败;通过foreach=False显式绕过。NPU 运行保持默认 foreach/fused 路径。已知限制:
device_type探测当前仅覆盖 npu/cpu,纯 GPU 环境会回落到 cpu(待补齐,见 §14)。
12. 平台边界
compile/是平台分层规则的显式 Torch-only 例外(与core/multicore同类处理):依赖 patched autograd engine、
torch.fx与 functionalcollectives 的图内表示,这些均无平台无关抽象。模块内直接 import torch
是有意为之,
compile/README.md已记录该例外。get_platform()级抽象后,再评估MindSpore 支持。
PassConfig/PassPlan/PassPipeline不 importtorch(
torch.fx仅TYPE_CHECKING延迟导入),使配置与编排可被其他后端复用。
13. 测试覆盖
tests/ut/compile/(单卡 UT):test_tracer.py:捕获契约(静态输入、joint 图、元数据);test_fsdp_pass.py:collective 插入、live model 分片;test_pass_pipeline.py:流水线组装与 pass 选择;test_parallel_config.py/test_sharding_plan.py:配置与 YAML 契约;test_auto_overlap.py:wait_tensor识别与调度;test_tpsp.py:TP/SP 适配契约;test_trainer.py:训练循环、梯度映射、FSDP 门控。后续补齐:
torchrun_case);14. 后续演进(TODO)
按优先级:
_move_wait_later真实现——依赖分析 + 将wait_tensor下沉到首个使用者之前。FSDPModuleConfig曾以 dead surface 移除reshard_after_forward/use_cpu_offload/wrap_separately;待真实 pass 落地时带真实消费方再加回。
规划中;PP 需要 schedule 与 micro-batch 在图上的表示,执行层扩展位在
PassPipeline的分区层。PassPipeline接入 inductor / NPU 图编译后端。docs/guide/graph_mode.md用户指南;清理示例 YAML 中未被parser 消费的字段。
schema_version: 1
source: gitcode
gitcode_repo: mindspore/hyper-parallel
gitcode_issue: 381
source_url: https://gitcode.com/mindspore/hyper-parallel/issues/381