作者​:昇腾实战派
知识地图​:https://blog.csdn.net/Lumos_Lovegood/article/details/161601003

背景概述

随着大模型训练场景的多样化发展,模型需要在不同硬件平台上保持一致的训练精度。本工作旨在将 GLM-5.2 模型结构接入 MindFormers PyNative 框架,并以 GPU 上的 Megatron-LM 为参考基准,验证 Ascend NPU 与 NVIDIA GPU 在单卡训练场景下的精度一致性。通过系统化的对齐流程,确保模型在不同硬件平台上的训练行为可复现、可预期,为后续多卡扩展和实际应用奠定基础。

4 层 mini GLM-5.2 到 1B 级 GLM-5.2 单卡精度对齐,不包含 hidden_size=6144 的 8 卡任务。

1. 工作目标

本工作的目标是将 GLM-5.2 结构接入 MindFormers PyNative,并以 GPU Megatron-LM 为参考,验证 Ascend NPU 与 NVIDIA GPU 的训练精度是否一致。

对齐时重点检查两个指标:

  • loss:模型预测结果与训练目标之间的误差。
  • grad_norm:所有参数梯度的整体大小,反映反向传播和参数更新是否一致。

误差统一定义为:

每步误差 = NPU - GPU
ME = 所有训练步误差的平均值

最终采用的判定目标为:

指标目标
lossabs(ME) < 0.001
grad_normabs(ME) < 0.01

2. 总体流程

MindFormers PyNative 构建 GLM-5.2
              ↓
mini 模型依次验证 Transformer、DSA、MoE、MTP
              ↓
NPU 训练 base model 并保存权重
              ↓
将权重统一转换为 BF16
              ↓
将 BF16 权重转换为 Megatron-LM 可加载格式
              ↓
NPU 与 GPU 加载同源权重、读取同源数据
              ↓
分别训练并比较 loss、grad_norm

使用同源权重和同源数据,是为了确保曲线差异来自框架或算子实现,而不是随机初始化或样本不同。

3. 第一阶段:mini GLM-5.2

3.1 目的

先使用较小配置打通完整训练链路,降低定位问题的成本。该模型用于代码和精度验证,不代表正式 GLM-5.2 的模型规模。

3.2 配置

项目配置
Transformer 层数4
hidden size128
vocabulary size128
sequence length16
模型结构DSA + MoE + MTP
DSA top-k2048
MoE top-k2
参数类型BF16
优化器AdamW
学习率1e-5
最终训练步数200

3.3 最初 10 步基线

早期版本已经能够在 NPU 和 GPU 上运行,但两端尚未完成精度对齐。下图记录了当时的真实 loss 和 grad_norm,是后续排错的起点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

初期 10 步结果:

指标平均绝对差最大绝对差
loss0.0238600.047647
grad_norm0.2744540.950350

这组数据没有达到对齐目标,主要用于证明“代码能运行”不等于“训练精度已经对齐”。

3.4 主要问题与修改

问题修改作用
NPU 与 GPU 的 Attention 输出维度解释不同FA 输出展平前显式恢复维度顺序保证输出投影读取相同的向量排列
routed expert W1 权重方向不同转换时对 W1 转置对齐 MoE 专家线性层
shared expert FC1 的 SwiGLU 排列不同将交错排列转换为 Megatron 的前后分块排列对齐 gate/up 两部分权重
GPU 未完整加载 router 状态增加 expert_bias 映射GPU 权重加载达到 127/127
两端 TopK expert 顺序不同NPU TopK 按 expert 编号排序固定相同的专家选择顺序
AdamW 与 BF16 写回细节不同GPU 对齐 NPU 更新公式,并按 BF16 写回参数减少多步训练后的参数漂移
Attention scale 不一致GPU 恢复 k_channelsv_channels两端统一使用 1/sqrt(192) 缩放

关键权重转换示例:

# routed expert W1:修正权重方向
converted[target_key] = value.T.copy()

# shared expert FC1:从交错布局转为 [gate; up]
row_index = np.concatenate([
    np.arange(0, row_count, 2),
    np.arange(1, row_count, 2),
])
converted[target_key] = value[row_index]

3.5 mini 最终结果

使用相同输入文件和相同初始 BF16 权重,在 NPU MindFormers 与 GPU Megatron-LM 上训练 200 步。

输入文件 SHA256 均为:

5b207e7d346155bbb1e3e3309a2a32fdbd4b3a176f39137e3603c6d03249225f

该值是文件指纹。两端指纹相同,说明输入文件内容完全一致。

指标MEmax errormin error结果
loss+0.0002275813+0.0025243759-0.0009393692通过
grad_norm+0.0050740123+0.6322510242-0.6356949806通过

mini 模型完成了 DSA、MoE、MTP 全链路的单卡精度验证,为扩大模型规模提供了可用基线。

4. 第二阶段:1B 级 GLM-5.2

4.1 目的

mini 模型通过后,将模型扩大到 1B 级测试配置,并恢复正常词表、较长序列和更完整的层数,验证误差在更接近实际训练的条件下是否仍可控。

4.2 配置

项目配置
Transformer 层数24
hidden size1024
attention heads32
vocabulary size154880
sequence length1024
FFN hidden size2048
前置 Dense 层数3
DSA / MLA开启
DSA index heads / top-k32 / 1024
routed / shared experts8 / 1
experts per token2
MTP 层数 / loss scale1 / 0.3
参数与计算类型BF16
学习率1e-5

4.3 同源权重和数据

本阶段不再让两端分别随机初始化,采用以下流程:

  1. NPU PyNative 先训练 10 步,保存 base model。
  2. 将 base model 转换为统一 BF16 权重。
  3. 将 BF16 权重转换为 Megatron-LM 权重。
  4. NPU 加载 BF16 权重,GPU 加载转换后的同源权重。
  5. 两端读取同一个 1000 步 next-token 数据文件。

数据文件 SHA256:

30145a6260875f713e7dd81f4af121f7c0e4ba0da0c391644d3e751f83adcfd6

4.4 扩大模型后发现的问题

Dense FFN 权重布局

NPU FC1 按 [gate0, up0, gate1, up1, ...] 交错保存;Megatron 按 [全部 gate, 全部 up] 保存。转换时增加去交错操作:

if op == "deinterleave_glu_rows":
    rows = value.shape[0]
    order = np.concatenate((
        np.arange(0, rows, 2),
        np.arange(1, rows, 2),
    ))
    return value[order].copy()
GPU 激活函数

GPU 只开启了 GLU,但未显式指定 SiLU,Megatron 实际使用 GELU;NPU GLM-5.2 使用 SiLU。修复为:

import torch.nn.functional as F

cfg = MLATransformerConfig(
    gated_linear_unit=True,
    activation_func=F.silu,
)

修复后,第 1 步 grad_norm 差值由约 -0.194 降到 -0.00539,20 步 grad_norm ME 由 -0.14080 降到 -0.00296

稀疏 DSA 的确定性

NPU 原生稀疏 DSA 的 TopK 和部分并行算子存在非确定性。正式实验固定 TopK 顺序并开启确定性计算:

ms.set_context(
    mode=ms.PYNATIVE_MODE,
    device_target="Ascend",
    deterministic="ON",
)

4.5 1B 最终曲线

以下为同源权重、同源数据、确定性模式下的 1000 步结果。红线为 NPU MindFormers,绿线为 GPU Megatron-LM。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

误差图采用 NPU - GPU,保留正负号:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.6 1B 最终结果

指标MEmax errormin error结果
loss-0.0001127071+0.0078821182-0.0082559586通过
grad_norm-0.0092500153+0.4218254089-0.4344191551通过
mtp1_loss+0.0000002556+0.0017435551-0.0014431477对齐
load_balancing_loss+0.0000028539+0.0047043562-0.0040243268对齐

结果说明:

  • NPU 与 GPU 的 loss 曲线基本重合,1000 步 loss ME 满足目标。
  • grad_norm 单步会出现正负波动,但平均误差仍小于 0.01。
  • MTP loss 和 MoE load balancing loss 同时保持较小平均误差,说明主损失之外的辅助训练分支也已接入并对齐。

5. 阶段结果汇总

阶段规模步数loss MEgrad_norm ME结论
mini 最终实验4 层,hidden 128200+0.0002275813+0.0050740123通过
1B 最终实验24 层,hidden 10241000-0.0001127071-0.0092500153通过

6. 结论

本工作已完成以下内容:

  1. 在 MindFormers PyNative 中打通 GLM-5.2 的 Transformer、DSA、MoE、MTP 训练链路。
  2. 建立 NPU base model 到 BF16、再到 Megatron-LM 权重的转换流程。
  3. 找到并修复 Attention、MoE、SwiGLU、激活函数、优化器和确定性计算等差异。
  4. 完成 mini 模型 200 步与 1B 级模型 1000 步单卡 GPU/NPU 精度对齐。
  5. 最终 1B 实验满足 |loss ME| < 0.001|grad_norm ME| < 0.01

当前结论只适用于本报告中的单卡、hidden_size=1024 及以下实验。hidden_size=6144 的多卡任务需要单独完成 GPU/NPU 训练和误差统计,不能直接沿用本报告的数值结论。

Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐