Skip to content

[Bug] GLM53 mHC FP32 parameter gradients miss the FSDP dimension #2136

Closed as not planned

Description

@bingshao333

GLM53 的 mHC FP32 hc_*_base/scale 只在 EP 组内归约梯度,遗漏 FSDP 维度。在 FSDP2×EP4 的 8 卡训练中,两组参数从相同初值更新后发生分叉。

复现版本:尚未合入 main 的 #2111,commit 016500f04780bdb1c29eb932497a1eb19e4c5444。

原因

  1. _replicate_other_params 先把非 expert 参数放到 EP 或 EP×ETP 的 Replicate mesh。
  2. _fully_shard 为保持 FP32,将已有 DTensor 的 base/scale 直接加入 ignored_params,保留原 mesh。
  3. scale_and_reduce_grad 只沿参数 mesh 的 Replicate 维度归约,因此没有覆盖 FSDP。

复现与结果

环境为 8×H200、PyTorch 2.9.1+cu128、Triton 3.5.1。模型使用随机初始化的两层 GLM53(一个 Dense KDA 层、一个 MoE KDA 层),D=256、hc_mult=4、20 轮 Sinkhorn、8 个 routed experts、EP=4、ETP=1;关闭 compile 和 recompute,参数计算 dtype 为 BF16,mHC base/scale 保持 FP32。

复现步骤:

  1. 确保 mHC 参数初值在 8 卡相同,每个 rank 使用不同的随机 token/label,local batch 为 [1,128],计算 token 平均交叉熵并 backward。
  2. 收集全部 ranks 的原始 base/scale 梯度,计算其全局平均,作为归约参考。
  3. 调用 model.scale_and_reduce_grad(),比较实际梯度与参考,然后执行 SGD(lr=0.1、无 momentum/weight decay),检查各 rank 参数。

实际只得到两个组内平均,缺少两组之间的归约:

rank 0–3  → g_A
rank 4–7  → g_B
预期:全部 ranks 得到 (g_A + g_B) / 2。
指标 原实现 mHC world Replicate 实验对照
首步更新后最大参数副本差 2.96533e-4 0
三步内最大参数副本差 5.19216e-4 0

对照只在 FSDP 包装前,将 mHC base/scale 改为 world Replicate。该实验确认漏同步及其对参数更新的影响,未覆盖完整 checkpoint 训练或长期收敛。

影响范围与建议修复

对当前普通 FSDP 路径,触发条件为 (EP>1 或 ETP>1) 且 world_size/(EP×ETP)>1;ETP 情况由代码路径推导,尚未实测。EP=ETP=1 不触发这条遗漏路径。hc_*_fn 仍由 FSDP 管理。

建议在 Glm53TextMoE._replicate_other_params 中调用父类方法后,仅将 hc_(attn|ffn)_(base|scale) 补全为 world Replicate,保持 FP32,并复用现有梯度归约。生产修复需验证全局梯度平均、更新后副本一致性和 checkpoint 保存/恢复。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions