Open
[RFC]Hyper Parallel支持图模式 #381
kisnwangAdd on Sep 10
Sep 14 Associated pull request
Sep 14 Deleted associated pull request: feat(compile):create graph text trainer and adaption with symint dynamic shapes
Sep 14 Deleted associated pull request: feat(compile):create graph text trainer and adaption with symint dynamic shapes
Sep 14 Associated pull request
Sep 15 Associated pull request
Sep 30 Associated pull request
28 days ago Associated pull request
27 days ago Associated pull request
Yyangzhenzhang
26 days ago Change title to "[RFC]Hyper Parallel支持图模式", originally titled "[RFC] Graph Mode(hyper_parallel/compile)设计方案".
26 days ago Change title to "[RFC]Hyper Parallel支持图模式", originally titled "[RFC] Graph Mode(hyper_parallel/compile)设计方案".
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 消费的字段。