合并受阻
变更摘要
此 PR 将 GLM-4.5V (106B MoE-VLM) 从 megatron-FSDP2 路径迁移到纯 FSDP2 后端 (mindspeed_mm/fsdp/),去除对 Megatron 的运行期依赖。通过新增模型注册 glm4v_moe、MoE 专家权重的 3D 堆叠布局、NPU 融合算子以及配套的配置/脚本/校验工具,形成一个独立的纯 FSDP2 训练路径;对既有 megatron 路径和其他模型无行为变更,转换器改动向后兼容。
主要改动
-
纯 FSDP2 模型注册与 NPU 融合:在
mindspeed_mm/fsdp/models/glm4_5v/modeling_glm4_5v.py中新增Glm4vMoeFSDPForConditionalGeneration,通过@model_register.register("glm4v_moe")注册,薄封装 HF 的Glm4vMoeForConditionalGeneration;NPU 环境下替换为融合 RMSNorm(npu_rms_norm)、融合 RoPE(npu_rotary_mul)以及 bilinear grid_sample 的 vision embeddings,非 NPU 自动回退原生 HF 实现。 -
MoE 专家 3D 堆叠权重布局:新增
Glm4vMoeTextExperts类,专家权重保持(E, hidden, 2*inter)/(E, inter, hidden)的 3D 形状,以适配框架专家并行的Shard(0)+npu_grouped_matmul合约;同时在checkpoint/vlm_model/converters/moe_expert.py中新增ConfigType.GLM4V = 3,由环境变量GLM4V_DCP_3D=1显式开启 3D 布局,默认保持上游 2D 展平以兼容 megatron 路径。 -
训练配置与启动脚本:新增
examples/glm4.5v/glm4_5v_full_sft_106B.yaml(纯 FSDP2 SFT 配置,含 fsdp_plan / ep_plan / chunkloss / recompute 等)、finetune_glm4_5v_106B_fsdp.sh(设置NON_MEGATRON=true并调用mindspeed_mm/fsdp/train/trainer.py)、以及convert_glm4_5v_ckpt.sh(HF → 3D DCP 的 checkpoint 转换脚本,通过mm-convert+GLM4V_DCP_3D=1实现)。 -
跨后端对拍工具链:新增
token_dump.py(通过 patch_BaseDataLoaderIter.__next__实现 token 流 dump 与逐位 diff)、compare_runs.py(解析训练日志对比逐步 loss 相对误差和吞吐性能)、preflight_check.py(CPU-only 预检 yaml 中各 plan 的模块名模式是否匹配实际模型树)、verify_expert_layout.py(验证 3D 堆叠布局与 HF 逐专家前向的数值一致性)等辅助脚本。 -
数据管线与 megatron dump 适配:新增
dump_entry_megatron.py(绕过 megatron 侧 dataloader hook 失效问题,直接包装pretrain_transformers.get_batch以 dump token 流)和make_compare_dataset.py(基于 LLaVA-Instruct-150K + COCO 构建小规模跨后端对比数据集)。


代码审查
审查总结
共审查 14 个变更文件,发现 4 个问题:
| 优先级 | 数量 | 说明 |
|---|---|---|
| P1 | 1 | modeling_glm4_5v.py — Glm4vMoeTextExperts.forward 中 expert_output[0] 错误地仅用首个 token 的投影输出 |
| P2 | 2 | verify_expert_layout.py — 相同 [0] 缺陷,验证结果不可信;finetune_glm4_5v_106B_fsdp.sh — 缺少 set -euo pipefail |
| P3 | 1 | make_compare_dataset.py — COCO 图片下载使用 HTTP 明文,应改用 HTTPS |
逐文件确认
| 文件 | 审查结论 |
|---|---|
checkpoint/vlm_model/converters/moe_expert.py |
无问题 — GLM4V config type 新增及环境变量门控逻辑正确 |
docs/zh/features/fsdp2_glm4_5v_migration_practice.md |
无问题 — 文档无安全/配置风险 |
docs/zh/features/fsdp2_glm4_5v_performance_practice.md |
无问题 — 文档无安全/配置风险 |
examples/glm4.5v/compare_runs.py |
无问题 |
examples/glm4.5v/convert_glm4_5v_ckpt.sh |
无问题 — set -e 已设置,变量已引用 |
examples/glm4.5v/dump_entry_megatron.py |
无问题 |
examples/glm4.5v/finetune_glm4_5v_106B_fsdp.sh |
P2: 缺少 set -euo pipefail |
examples/glm4.5v/glm4_5v_full_sft_106B.yaml |
无问题 |
examples/glm4.5v/make_compare_dataset.py |
P3: HTTP 明文下载图片 |
examples/glm4.5v/preflight_check.py |
无问题 |
examples/glm4.5v/token_dump.py |
无问题 |
examples/glm4.5v/verify_expert_layout.py |
P2: expert_output[0] 与模型代码相同缺陷 |
mindspeed_mm/fsdp/models/glm4_5v/__init__.py |
无问题 — 空的包标记文件 |
mindspeed_mm/fsdp/models/glm4_5v/modeling_glm4_5v.py |
P1: expert_output[0] 逻辑错误 |
整体风险判断
中高风险。P1 问题影响非 EP 路径下的 MoE 专家前向计算正确性(单卡调试/tiny 验证场景触发),P2 验证脚本的相同缺陷使其验证结论不可信(该脚本被迁移文档引用为 3D 布局契约的静态验证手段)。建议在合入前优先修复 modeling_glm4_5v.py L144 和 verify_expert_layout.py L77,并同步复核 verify_expert_layout.py 验证结果。
| 类型 | 数量 |
|---|---|
| 🔴 阻塞 | 2 |
| 🟡 建议 | 4 |
⛔ 需要修改


| 阶段 | 任务名 | 状态 | 详情 |
|---|---|---|---|
| 编译构建 | Build | ✅ COMPLETED | >>> |
| 恶意代码检查 | Antipoison | ✅ COMPLETED | >>> |
| 编码安全与规范检查 | Only_doc_commit | ✅ COMPLETED | >>> |
| codeCheck_pre-commit | ✅ COMPLETED | >>> | |
| pre-commit | ✅ COMPLETED | >>> | |
| Compatibility_Interface | ✅ COMPLETED | >>> | |
| 开源片段检查 | SCA | ✅ COMPLETED | >>> |
| 开发者测试 | UT | ⚪ IGNORED | >>> |
| ST | ⚪ IGNORED | >>> | |
| UT-pool | ✅ COMPLETED | >>> | |
| ST_pool | ✅ COMPLETED | >>> | |
| 流水线 | PR-pipeline_MindSpeed-MM | ✅ COMPLETED | >>> |
- compile : 运行流水线
- retry : 重试流水线所有失败子任务
- retry <任务名> : 仅重试指定失败子任务
- stop : 停止流水线


What this PR does / why we need it?
将 GLM-4.5V 接入
mindspeed_mm/fsdp/的纯 FSDP2 后端,关联 #370。实践文档:模型开发 #560、性能优化 #562。glm4v_moe,复用 HF 模型及仓库的 CP、EP、EP Balance、ChunkLoss、recompute、activation offload 实现。GLM4V_DCP_3D=1显式开启转换,默认仍保留 Megatron 的 2D 布局。model.use_grouped_expert_matmul: false可使用逐专家参考路径,非 NPU 使用参考路径。EP>1 仍由仓库 dispatcher 处理。npu_patch.py;指南及启动脚本采用README_v1.md/finetune_glm4_5v_106B_v1.sh。转换命令直接放在指南内,原 MegatronREADME.md不修改,不提交临时诊断脚本。Does this PR introduce any user-facing change?
新增纯 FSDP2 训练路径。通过
NON_MEGATRON=true与mindspeed_mm/fsdp/train/trainer.py加载示例 YAML。使用方式及配置见 README_v1.md。buffer 的 BF16 对齐是本轮跨后端实验条件,没有默认改变通用 Trainer 或其他模型的 buffer 精度;直接运行默认 106B YAML 不等于复现下述减层对拍。
How was this patch tested?
2026-10-11:保留 128 专家的 8 卡对拍
8 × Ascend 910B3,文本/视觉各 4 层,128 routed experts、top-k 8,EP=1、CP=1、FSDP=8;固定 2048 条真实 LLaVA/COCO 图文样本,micro batch=1、global batch=8、seed=1234。两端从对应初始 DCP 起训,初始 104 个张量经布局映射后逐元素一致。
误差使用
mean(abs(pure_loss-megatron_loss)/(abs(megatron_loss)+1e-8))*100,包含全部 2000 步,不丢弃尖峰。这是该减层配置、单次 seed=1234 运行的平均指标通过,不是每步误差 <2%,不是完整 106B 或 EP>1 的新验证。 第 1001~1500、1501~2000 步区间平均误差分别为 2.942306%、2.468621%,仍存在训练后段分歧。本轮模型运行源码与本次提交中的
modeling_glm4_5v.py一致,SHA-256 为67a4be854f40a237aa21bb3b0fc9c7b1fd6cc805640ce13e83c71e5f9addb50d。新完整运行另使用训练前 buffer 对齐入口;其关键处理见下方。后续新增的 CPU 测试、文档和启动脚本检查不冒充新的 NPU 重跑。图表由 TrainingLogParser 直接解析两端原始日志生成,Comparison step=1,无平滑,Megatron 为分母;横轴 0 对应训练第 1 步,红线 0.02 为 2%。已核验 2000 点及图表统计与独立脚本一致。训练拉起截图见性能实践文档中的训练截图。
本轮对拍配置、buffer 前处理与证据标识
与默认示例相比,模型目录和
training.load指向同一套减层模型的 pure 3D DCP,数据预处理目录指向对应 HF 配置。shuffle=false,cutoff_len=1024,num_workers=0,enable_preload=false;训练从初始权重开始,不恢复 optimizer/RNG。model: attn_implementation: sdpa use_grouped_expert_matmul: true freeze: - model.visual.patch_embed - model.visual.blocks - model.visual.merger features: enable_chunk_loss: false enable_dynamic_chunk_loss: false enable_activation_offload: false enable_ep_balance: false loss_cfg: loss_type: default router_aux_loss_coef: 0.0 recompute: true recompute_plan: apply_modules: - model.visual.blocks.{*} - model.language_model.layers.{*} use_reentrant: true training: train_iters: 2000 seed: 1234 micro_batch_size: 1 gradient_accumulation_steps: 1 lr: 1.0e-5 lr_decay_style: cosine lr_warmup_ratio: 0.1 weight_decay: 0 clip_grad: 0.0 no_load_optim: true no_load_rng: true save: ''Megatron 的实际 attention 为 SDPA;其冻结范围只覆盖上面三个视觉子模块,其余视觉参数仍训练。其 Float16Module 将浮点 buffer 一同转成 BF16;pure 的 FSDP 参数混合精度不会这样处理。首个前向差异定位在视觉 RoPE 的 cos/sin。对齐 buffer 后,首步记录的 42 个张量字段(含 logits)逐元素一致。
独立验证入口在构建 Trainer 前安装如下包装,作用点为模型准备后、加载初始检查点前;FP32 参数和整数 buffer 不转换。该包装未放入生产 Trainer,也不是默认配置。可将它用于仓库外的实验入口,之后正常构建
Trainer(args=ConfigManager(config_class=Arguments).load_and_parse())并调用train();不要把训练步数改成短测步数后与 2000 步学习率计划比较。import torch from mindspeed_mm.fsdp.train.trainer import Trainer, ConfigManager, Arguments original_get_model = Trainer.get_model def get_model_with_bf16_buffers(self, *args, **kwargs): model = original_get_model(self, *args, **kwargs) for module in model.modules(): for name, buffer in module.named_buffers(recurse=False): if buffer.is_floating_point(): module._buffers[name] = buffer.to(torch.bfloat16) if hasattr(module, 'original_inv_freq') and hasattr(module, 'inv_freq'): module.original_inv_freq = module.inv_freq return model Trainer.get_model = get_model_with_bf16_buffers trainer = Trainer(args=ConfigManager(config_class=Arguments).load_and_parse()) trainer.train()BF16 buffer 只用于复现既有 Megatron 的数值语义,不意味着 BF16 RoPE 比 FP32 更准确。仅启用 grouped-MoE 主要改善了性能,并不足以消除原来的精度差异。
原始日志、配置、运行库版本、Git diff、实际 buffer dtype、完整性检查和脚本已归档,证据包 504600 字节,SHA-256
009fdafdb233b376efbeaa52f44c4545d11838fd09652f7e3072963d69702b63,内部 80 个文件校验通过。本轮未保存新的训练后 checkpoint。Megatron 原始基线日志 SHA-256 为7f2d944957223b28f8633f43c0b4444d6ff47e929d155393dd15b2b011902f51。本地回归与历史证据
git diff --check、YAML 解析、Bash 语法、文档相对路径与 Bandit(仓库配置)检查通过。本地未运行完整 pre-commit 门禁;以新提交的 CI 结果为准。README_v1.md为准。本次更新 PR,不改写历史实践 issue。人工评审意见核对
以上是代码与证据的逐项核对,不代替评审者确认。现有讨论的 resolved 状态和
stat/needs-squash标签保留,待维护者复核及合入处理。机器人历史意见也已核对:ChunkLoss 的静态/动态开关显式绑定到模型,已有实际 loss/梯度测试;专家输出的索引疑问由当前标量 expert index 和多 token 前向/梯度对照覆盖,旧独立验证脚本已移除。启动脚本先检查 CANN 环境加载返回码,再启用
set -euo pipefail,避免训练失败被tee掩盖,也避免把严格 shell 选项带入 CANN 环境脚本。旧数据下载辅助脚本亦已移出 PR。