已开启
feat: Support GLM-4.5V on the pure-FSDP2 backend (issue #370) #2875
feat: Support GLM-4.5V on the pure-FSDP2 backend (issue #370) #2875
已开启
SuperKoalaKing创建于 7月23日
7月23日

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 实现。
  • 专家权重使用 3D 堆叠布局;GLM4V_DCP_3D=1 显式开启转换,默认仍保留 Megatron 的 2D 布局。
  • NPU EP=1 使用 token permute → grouped-GEMM → SwiGLU → grouped-GEMM → unpermute;model.use_grouped_expert_matmul: false 可使用逐专家参考路径,非 NPU 使用参考路径。EP>1 仍由仓库 dispatcher 处理。
  • RoPE patch 独立在 npu_patch.py;指南及启动脚本采用 README_v1.md / finetune_glm4_5v_106B_v1.sh。转换命令直接放在指南内,原 Megatron README.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 个张量经布局映射后逐元素一致。

指标 实测结果
对拍步数 1~2000 完整,无缺失或重复
平均 loss 相对误差 1.617965% < 2%
最大单步相对误差 14.324236%(第 1245 步)
Megatron / pure 平均耗时 922.725 / 903.014 ms/step
训练退出码 / LR 不一致数 0 / 0

误差使用 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 重跑。

128 experts, 2000-step TrainingLogParser comparison

图表由 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。

本地回归与历史证据

  • 模型 CPU UT 26 项通过:文本/MoE 前向与梯度、grouped-MoE 的实际分组/路由算术和梯度、未命中专家梯度、静态/动态 ChunkLoss、CP 切分/汇总、EP Balance 配置、RoPE、logits 选择和启动配置。NPU 基础算子在 CPU UT 中用可微 CPU 实现替代;实际 NPU 运行见上面的 2000 步结果。
  • git diff --check、YAML 解析、Bash 语法、文档相对路径与 Bandit(仓库配置)检查通过。本地未运行完整 pre-commit 门禁;以新提交的 CI 结果为准。
  • 旧的 0.378% 结果属于先前 tiny 同构模型(8 专家)的 2000 步实验,不能当作本次 128 专家或完整 106B 模型结果。旧 CP/EP/ChunkLoss/offload 等特性开关与压力测试记录保留在 #562,其规模、提交和限制以该文档标注为准,不视为本次新提交的全量 NPU 回归。
  • 两篇实践 issue 中提到的历史调试脚本已移出当前 PR,不应按当前分支路径直接运行;当前训练、转换入口以 README_v1.md 为准。本次更新 PR,不改写历史实践 issue。

人工评审意见核对

评审意见 当前落实情况
实践文档、训练截图、TrainingLogParser 图 #560/#562 已提供;本次追加 128 专家完整 2000 步曲线与限定条件
删除 compare_runs.py 中不必要的生成内容 该临时文件已从 PR 移除
不需要独立转换脚本,放到 README 转换脚本已移除,HF↔DCP 命令写入 README_v1.md
不提交调试代码 verify_expert_layout/token_dump/preflight 等临时脚本不在 PR 文件清单中
patch 抽成 npu_patch.py 已独立,按模型插件方式注册
使用 README_v1.md 和 *_v1.sh 命名 已按仓库风格命名,原 README.md 保持不变
增加功能测试,不只判断类型 已补充上述前向/梯度数值测试,26 项通过

以上是代码与证据的逐项核对,不代替评审者确认。现有讨论的 resolved 状态和 stat/needs-squash 标签保留,待维护者复核及合入处理。

机器人历史意见也已核对:ChunkLoss 的静态/动态开关显式绑定到模型,已有实际 loss/梯度测试;专家输出的索引疑问由当前标量 expert index 和多 token 前向/梯度对照覆盖,旧独立验证脚本已移除。启动脚本先检查 CANN 环境加载返回码,再启用 set -euo pipefail,避免训练失败被 tee 掩盖,也避免把严格 shell 选项带入 CANN 环境脚本。旧数据下载辅助脚本亦已移出 PR。

likedislike
合并受阻
SSuperKoalaKing
7月23日 创建了 pull request,commit a8a12d99
SSuperKoalaKing
7月23日 关联了issue:[Feature]: 基于FSDP2后端训练MM大模型
atomgit-bot
atomgit-bot
7月23日 评论:

变更摘要

此 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 构建小规模跨后端对比数据集)。

likedislike
不准确?
atomgit-bot
atomgit-bot
7月23日 评论:

代码审查

审查总结

共审查 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

⛔ 需要修改

likedislike
不准确?
ascend-robotascend-robot成员
7月23日 添加了label:ascend-cla/yes
此处折叠了246条消息 查看更多
ascend-robotascend-robot成员
1 天前 添加了label:docs-ci-pipeline-success
ascend-robotascend-robot成员
1 天前 删除了label:ci-pipeline-running
ascend-robotascend-robot成员
1 天前 添加了label:ci-pipeline-passed
ascend-robot
ascend-robot成员
1 天前 评论:
流水线 PR-pipeline_MindSpeed-MM#5110 [ commitID:5ab883b0 ] 已完成
>>>代码风格自动修复执行成功(无修复内容)
阶段 任务名 状态 详情
编译构建 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 >>>
此流水线已支持下列评论快捷指令,仅PR创建者和白名单成员[wujinyuan1, htwang, hhhzhuyizhi, cxiaolong, bigdog1206, ghoshaw, yaoyaoxu]评论有效
  • compile : 运行流水线
  • retry : 重试流水线所有失败子任务
  • retry <任务名> : 仅重试指定失败子任务
  • stop : 停止流水线
likedislike
SSuperKoalaKing
1 天前 修改了pull request 的描述