已关闭
【实践文档】:glm4.5v迁移纯FSDP2性能优化文档 #562
SuperKoalaKing创建于  8月4日关闭于  28 天前
SuperKoalaKing
8月4日 创建

GLM-4.5V 纯 FSDP2:特性适配与性能对拍

关联:任务 #370 · PR !2875 · 模型迁移实践 #560 · FSDP2 使用指南

本文记录 GLM-4.5V 迁移到纯 FSDP2 后的特性适配、开关对拍和长输入压力测试。测试模型是微型同构模型,结论不外推到 106B 完整模型。

目录:结论 · 适配内容 · 实验设置 · F200 单项对拍 · F500 组合对拍 · P32K 长输入压力 · 复现与边界 · 历史附录

1. 结论

所有开关在 F200、F500、P32K 各组内都完成了 loss 对拍,平均相对误差均低于 0.001%,最大为 0.000871%(P32K Ulysses CP2)。下表只列性能和显存。

特性 测试组 关键数据 结论
Static ChunkLoss F200 max-rank allocator 峰值 -39.568%;吞吐 -2.86% 显存收益明确,速度代价小
Dynamic ChunkLoss F200 显存峰值与 Static 相同 路径可用。没有记录逐步 chunk 大小,动态调整的额外收益未验证
EP1→EP8 F200 吞吐 +24.58% 有速度收益
EP Balance F200 各 rank 平均负载 CV 0.691664→0,总 assignments 守恒;吞吐 -3.89% 负载均衡生效,端到端没有加速
Recompute P32K max-rank allocator 峰值 -32.88%;吞吐 -20.45% 用计算换显存
Ring / Ulysses CP F200、P32K F200 吞吐 -56.95% / -52.60%;P32K Ulysses CP2 吞吐 -46.40%,显存上升 切分路径正确,这些负载下没有容量或速度优势
Async Activation Offload F200、P32K 观测到 D2H/H2D;P32K allocator 峰值 -1.35%,HBM 采样不变 路径生效,显存收益不明显;P32K 40 步轮退出码未知

2. 适配内容

特性 完成的工作
Ring CP / Ulysses CP 文本 embeddings、position IDs 按 CP 切分;视觉 packed sequence 的 hidden states / RoPE 按图像序列切分;Ring 设置本地 cu_seqlens 和 seq_split_lens;视觉合并前后复用仓库 gather/split;最终 loss 按 CP group 汇总
EP MoE 专家采用 3D 堆叠权重,对接仓库的专家维分片、dispatcher 和融合专家运算;保留 EP1 参考路径;转换器通过 GLM4V_DCP_3D=1 选择 3D 布局
EP Balance 把负载均衡开关和 max_dup_experts_num 传入模型,复用仓库的专家复制、重分配和通信机制
Static/Dynamic ChunkLoss 两种开关显式绑定到模型实例,forward 走框架改写后的 lm_head/loss 路径,避免开关被忽略;static/dynamic 分别验证
Recompute 按仓库 recompute plan 包装视觉 blocks 和语言模型 layers
Async Activation Offload 按仓库 activation-offload plan 接入激活卸载/回载;off/on 对照两侧的 recompute 设置相同

模型代码在 mindspeed_mm/fsdp/models/glm4_5v/modeling_glm4_5v.py,另有训练配置、启动脚本和权重转换。重计算、卸载、EP 调度和 chunk-loss 运算复用仓库已有实现。NPU 路径使用融合 RMSNorm 和 RoPE,RoPE patch 单独放在 npu_patch.py。

第 4–6 节的上卡数据均采自提交 6ea63c3ddb104dd2aecc4e68886b233eb7430e94。 之后的文档、重构和 UT 提交没有重新上卡。

3. 实验设置

3.1 实验分组

实验组 数据与工作量 训练 / loss 对拍 性能统计区间 独立诊断
F200:单项特性 2048 条固定图文样本,cutoff=1024,micro=1,global batch=8 200 步 step 101–200 30 步逐 rank 显存、EP 探针;rank 0 step 20–24 profiler
F500:组合特性 同 F200 500 步 step 101–500 同 F200
P32K:Recompute / Offload 512 条合成长输入,cutoff=32768,micro=64,global batch=512 40 步 step 11–40 12 步显存;rank 0 step 10–12 profiler
P32K:Ulysses CP 同上数据,cutoff=32768,micro=16,global batch=128 40 步 step 11–40 12 步显存;另有 micro=32/64 容量短探针

只在同组内比较 OFF/ON。F200 与 F500 之间、两个 P32K 组之间不比较绝对耗时。计时、显存、负载探针和 profiler 分别单独运行,诊断轮的耗时不计入性能表。

F200、F500 和短输入诊断共 31 个运行项(9 个 200 步运行、4 个 500 步运行、9 个显存诊断、2 个 EP 负载诊断、7 个 profiler),全部跑满预期步数并 exit 0,loss / grad norm 均为有限值。P32K 的运行状态见 6.4。

展开 F200 / F500 的完整配置
  • 单机 8 × Ascend 910B3(64 GiB/卡),CANN 9.1.0,Python 3.11。
  • 模型:GLM-4.5V-tiny-dcp 微型检查点,8 个 routed experts、8 个 attention heads。
  • 数据:固定 compare_data/data.json,2048 个图文样本,cutoff_len=1024,shuffle=false。cutoff 是上限,样本实际长度不一。
  • global batch=8、micro batch=1、seed=1234;bf16 参数 / fp32 reduction;AdamW、lr=1e-5、cosine、lr_warmup_ratio=0.1、weight_decay=0,loss_type=default。
  • CP1 使用 DP8、梯度累积 1;CP2 使用 DP4、梯度累积 2,保持 global batch=8。
  • 各运行从相同 DCP 路径加载,不恢复 optimizer/RNG。
  • loss 对拍使用全部步数;性能统计 200 步组取 step 101–200,500 步组取 step 101–500。
  • 显存诊断单独运行 30 步,记录 8 个 rank 的 allocator 峰值。
展开 P32K 的模型、数据构造与采样说明
  • 模型是 tiny 同构压力模型(文本 2 层、hidden size 128、8 routed experts),不是目标大模型。原 tiny 配置 max_position_embeddings=4096,本次只在隔离的 HF/DCP 副本中改为 32768;所有非配置文件逐个核对 SHA-256 一致,原权重未改。扩大位置上限只用于容量和速度压力测试,不代表长上下文语义质量。
  • 数据取自先前图文数据的真实图片和答案,每档 512 条;在用户消息中拼接其他样本的描述,作为固定的无关参考段落。这是确定性的合成长上下文数据,不是真实长文档。短探针抽查的 microbatch 输入都达到 32768 tokens(含图像和监督 token),但没有逐条保存 512 条样本的 token 长度。
  • micro=64 时 global batch=512,40 步内重复使用 512 条样本;CP 组 micro=16、global batch=128,循环遍历同一批 512 条。
  • 每轮 40 步,前 10 步预热,后 30 步统计 ms/iter 和 samples/s;loss 误差用全部 40 步计算。
  • NPU 显存来自另外的 12 步逐 rank allocator 诊断。npu-smi HBM 在同一个 12 步轮中采样,包含 allocator 之外的占用,和 allocator 峰值是两个指标。Profiler 单独采集 rank 0 的 step 10–12。

3.2 配置编号

F200 / F500 以公共参考配置 B 为基线:CP1 + EP8 + Static ChunkLoss + recompute,Offload 和 EP Balance 关闭。01–08 每个配置只在 B 上改一个开关。

正文表格按"OFF→ON"列出开关方向,图中则用下面的编号。第 4 节表格的"配置"列给出两者的对应关系。

编号 相对 B 的改动
00_baseline 无(即 B)
01_ring_cp2 加 Ring CP2
02_ulysses_cp2 加 Ulysses CP2
03_ep1 EP8 改为 EP1
04_chunkloss_off 关闭 ChunkLoss
05_dynamic_chunkloss Static 改为 Dynamic ChunkLoss
06_recompute_off 关闭 recompute
07_async_offload 开启 Async Offload
08_ep_balance 开启 EP Balance
09_full_ring Ring CP2 + EP8 + Static ChunkLoss + recompute + Offload + EP Balance
10_full_ulysses 同 09,CP 改为 Ulysses

3.3 指标定义

  • 平均 loss 相对误差:mean(abs(test-reference)/(abs(reference)+1e-8)) × 100%,按相同步数逐项对齐。
  • samples/s:global_batch_size × 1000 / mean(ms/iter);吞吐变化:(samples/s_on ÷ samples/s_off - 1) × 100%。
  • 显存节省:(memory_off - memory_on) / memory_off × 100%,负数表示占用增加。max-rank 是 8 个 rank 峰值中的最大值,avg-rank 是 8 个 rank 峰值的平均值。
  • allocator allocated、设备 HBM 采样和主机 RSS 是三个口径,分开报告。
  • 通信占比:profiler 同一窗口内的 Communication / Stage。Communication 包含 FSDP、EP、CP 的全部通信,不能当成单个特性的通信占比。

4. F200:单项特性对拍

4.1 精度与耗时

左侧为 OFF(reference),右侧为 ON(test)。

开关对照 配置 loss 平均相对误差 loss 最大绝对误差 ms/iter:off→on samples/s:off→on 吞吐变化
Ring CP1→2 00→01 0.000395% 0.000140 161.904 → 376.040 49.412 → 21.274 -56.95%
Ulysses CP1→2 00→02 0.000345% 0.000140 161.904 → 341.538 49.412 → 23.423 -52.60%
EP1→8 03→00 0.000329% 0.000180 201.699 → 161.904 39.663 → 49.412 +24.58%
ChunkLoss off→static 04→00 0.000345% 0.000140 157.271 → 161.904 50.868 → 49.412 -2.86%
ChunkLoss off→dynamic 04→05 0.000353% 0.000150 157.271 → 160.806 50.868 → 49.749 -2.20%
ChunkLoss static→dynamic 00→05 0.000336% 0.000130 161.904 → 160.806 49.412 → 49.749 +0.68%
Recompute off→on 06→00 0.000356% 0.000150 124.870 → 161.904 64.067 → 49.412 -22.87%
Async Offload off→on 00→07 0.000346% 0.000150 161.904 → 166.087 49.412 → 48.168 -2.52%
EP Balance off→on 00→08 0.000347% 0.000160 161.904 → 168.463 49.412 → 47.488 -3.89%

EP8 比 EP1 时延低 19.73%,吞吐高 24.58%。Static ChunkLoss、Offload、EP Balance 的吞吐损失在 2.5%–3.9% 之间;recompute 时延增加 29.66%。Ring / Ulysses CP2 在这个规模下都没有加速。

下图是上表 ms/iter 列的柱状图,蓝色为 OFF,橙色为 ON。

F200 各开关 OFF/ON 平均 ms/iter(step 101–200)

展开各配置相对 B 的误差、grad norm 与 P95/P99
配置 loss 平均相对误差 loss 最大相对误差 grad norm 平均相对误差 P95/P99 ms
00_baseline 0.000000% 0.000000% 0.0000% 171.3 / 173.5
01_ring_cp2 0.000395% 0.001211% 0.0278% 389.2 / 398.1
02_ulysses_cp2 0.000345% 0.001210% 0.0182% 354.6 / 360.8
03_ep1 0.000329% 0.001547% 0.0213% 217.7 / 224.7
04_chunkloss_off 0.000345% 0.001208% 0.0231% 167.0 / 170.2
05_dynamic_chunkloss 0.000336% 0.001110% 0.0202% 169.0 / 172.1
06_recompute_off 0.000356% 0.001292% 0.0208% 131.3 / 136.6
07_async_offload 0.000346% 0.001294% 0.0183% 177.2 / 182.2
08_ep_balance 0.000347% 0.001378% 0.0181% 176.9 / 183.5

Grad norm 取自训练日志(保留三位小数),不是逐参数的梯度检查。每个配置只跑了一次。

展开 8 张 loss 对拍图(每张 200 步)

读图说明:

  • 图由 TrainingLogParser 解析原始日志生成(匹配 loss:,Comparison step=1,不平滑),横轴 0 对应 step 1。
  • 图标题里的 baseline 都是配置 B,下半部分的相对误差也以 B 为分母。因此 EP1、ChunkLoss off、recompute off 三张图的方向与上表 OFF→ON 相反,具体数值以上表为准。
  • 上半部分两条 loss 曲线几乎重合,所以看起来只有一种颜色;差异看下半部分。红线是 2% 参考线。

CP 与 EP

01_ring_cp2 vs B

02_ulysses_cp2 vs B

03_ep1 vs B(EP1 vs EP8)

ChunkLoss

04_chunkloss_off vs B(ChunkLoss off vs Static)

05_dynamic_chunkloss vs B(Dynamic vs Static)

Recompute、Offload 与 EP Balance

06_recompute_off vs B(recompute off vs on)

07_async_offload vs B

08_ep_balance vs B

4.2 逐 rank 峰值显存

单位 GiB,统计 30 步内的 allocator allocated 峰值,不是设备总占用。

开关对照 配置 max-rank:off→on avg-rank:off→on max-rank 节省 avg-rank 节省
Ring CP1→2 00→01 0.712448 → 0.905637 0.686491 → 0.779462 -27.116% -13.543%
Ulysses CP1→2 00→02 0.712448 → 0.993389 0.686491 → 0.880695 -39.433% -28.289%
EP1→8 03→00 0.712447 → 0.712448 0.686490 → 0.686491 -0.000% -0.000%
ChunkLoss off→static 04→00 1.178923 → 0.712448 1.147315 → 0.686491 +39.568% +40.165%
ChunkLoss off→dynamic 04→05 1.178923 → 0.712448 1.147315 → 0.686491 +39.568% +40.165%
ChunkLoss static→dynamic 00→05 0.712448 → 0.712448 0.686491 → 0.686491 +0.000% +0.000%
Recompute off→on 06→00 0.727570 → 0.712448 0.699361 → 0.686491 +2.078% +1.840%
Async Offload off→on 00→07 0.712448 → 0.711997 0.686491 → 0.686064 +0.063% +0.062%
EP Balance off→on 00→08 0.712448 → 0.712466 0.686491 → 0.686508 -0.003% -0.002%

ChunkLoss 是唯一有明显显存收益的开关:Static 和 Dynamic 的 max-rank 峰值都下降 39.568%,avg-rank 下降 40.165%。recompute 节省 2.078%,Offload 只有 0.063%,后者不足以说明有收益。CP2 的峰值反而上升。

静态 chunk_size=1024,动态 total_chunk_size=4096。本轮没有记录每步实际的 chunk 数和大小,cutoff=1024 也不足以构成多 chunk 的长序列压力。表中是整体 allocator 的变化,不单独归因于 logits。

下图按配置编号排列,每个配置一组柱子(蓝色 max-rank,橙色 avg-rank),不是 OFF→ON 成对排列。例如 ChunkLoss 的 OFF 侧是 04_chunkloss_off(1.179 GiB),ON 侧是 00_baseline(0.712 GiB)。

F200 各配置 30 步 allocator 峰值(max-rank / avg-rank)

4.3 EP Balance 的负载与守恒

EP 负载探针单独跑 30 步,开关两侧各采集 120 次 dispatcher 调用。Workload 是本 rank 专家分到的 assignment 数之和,包含 top-k 重复和重计算产生的重复调用,不等于有效 token 数。

rank Balance off:平均 assignments/调用 Balance on:平均 assignments/调用
0 29.567 937.000
1 1016.783 937.000
2 851.467 937.000
3 436.433 937.000
4 1231.900 937.000
5 2183.667 937.000
6 314.900 937.000
7 1431.283 937.000

EP Balance off/on 各 rank 平均 assignments(对应上表)

指标 Balance off Balance on
各 rank 平均 workload 的 CV 0.691664 0
各 rank 平均 workload 的 max/mean 2.330487 1
逐次调用 CV 的均值 1.075280 0
逐次调用 CV 的最大值 1.561286 0
120 次调用总 assignments 899520 899520

开启 Balance 后,120 次调用中每次的跨 rank 总 assignment 数都与关闭时一致,且 8 个 rank 分到的数量相等。负载均衡生效了,但 4.1 的性能轮里没有因此加速。探针本身带额外的 collective,其耗时不计入性能数据。

4.4 Profiler:通信与 Offload

采集 rank 0 的 step 20–24。这里的时间只用于看通信构成,不替代 4.1 的性能数据。

配置 通信总时间 ms/step 未重叠通信 ms/step 重叠通信 ms/step Stage ms/step 通信占比
00_baseline 18.506 18.244 0.262 218.325 8.476%
01_ring_cp2 29.220 29.031 0.189 531.535 5.497%
02_ulysses_cp2 28.643 28.393 0.250 467.746 6.124%
03_ep1 5.716 5.651 0.065 276.479 2.068%
07_async_offload 15.612 15.498 0.113 229.148 6.813%
09_full_ring 29.238 29.088 0.150 556.379 5.255%
10_full_ulysses 28.261 28.142 0.119 507.694 5.566%

各特性的特征通信(5 步累计):

  • EP8(00_baseline):AlltoAllv 60 次,48.4817 ms;EP1 没有这项。
  • Ring CP2:Send / Receive 各 160 次,分别累计 2.99746 / 2.98328 ms。
  • Ulysses CP2:AlltoAll 480 次,12.64234 ms。

各操作的 elapsed 之和不等于未重叠的墙钟时间。

Offload。 启动日志确认卸载覆盖 model.visual.blocks.0/1 和 model.language_model.layers.0/1,对照两侧的 recompute 设置相同。

指标(5 个采样 step) off on
显式 D2H host 调用次数 0 15
显式 H2D host 调用次数 0 15
D2H host 调用累计时长 0 124.43 μs
H2D host 调用累计时长 0 124.57 μs
设备 PCIE DMA 次数 30 60
设备 PCIE DMA 累计时长 93.70 μs 387.72 μs
PCIE DMA 与 AI Core/Vector 计算区间重叠 0 μs 0 μs
200 步轮 host RSS 采样最大值 138.014 GiB 138.199 GiB

D2H/H2D host 时长是 CPU 端调用耗时,PCIE DMA 是设备端搬运时间。Host RSS 是每 10 秒对匹配进程的 VmRSS 求和,共享页会重复计数,不是节点独占物理内存的峰值。

卸载和回载都发生了,但 rank 0 时间线上 PCIE DMA 没有与计算重叠;加上显存只差 0.063%,这个配置下 Offload 没有体现收益。

5. F500:组合特性对拍

组合配置为 CP2 + EP8 + Static ChunkLoss + recompute + Async Offload + EP Balance,Ring 和 Ulysses 各跑一次(09、10),global batch 保持 8。08_ep_balance 也在 500 步下重跑一次作对照。

配置 loss 平均相对误差 loss 最大相对误差 平均 ms/iter P95/P99 ms samples/s
00_baseline 0.000000% 0.000000% 159.379 170.5 / 176.1 50.195
08_ep_balance 0.000382% 0.001781% 172.291 174.2 / 707.5 46.433
09_full_ring 0.000422% 0.002101% 395.904 401.1 / 1052.8 20.207
10_full_ulysses 0.000383% 0.001968% 379.201 382.8 / 1058.8 21.097

两种组合都跑满 500 步,相对 B 的 loss 平均相对误差为 0.000422% 和 0.000383%。08、09、10 的 P99 有明显长尾,表中保留实测值。

展开 3 张 500 步 loss 对拍图(读法同 4.1)

08_ep_balance vs B,500 步

09_full_ring vs B,500 步

10_full_ulysses vs B,500 步

6. P32K:长输入压力测试

这一组只测 Recompute、Async Offload 和 Ulysses CP2。同组 OFF/ON 使用相同的权重、数据、seed、optimizer 和 global batch。Recompute 与 Offload 共用 micro=64 的 OFF 基线;Ulysses CP 单独一组,micro=16。模型和数据构造见 3.1。

6.1 结果

特性对照 cutoff / micro loss 平均相对误差 ms/iter off→on samples/s off→on 吞吐变化 max-rank allocator GiB 12 步采样 HBM GiB
Recompute off→on 32K / 64 0.000040% 19806.3 → 24896.6 25.850 → 20.565 -20.45% 38.61 → 25.92 46.39 → 34.15
Async Offload off→on 32K / 64 0.000034% 19806.3 → 19823.8 25.850 → 25.828 -0.09% 38.61 → 38.09 46.39 → 46.39
Ulysses CP1→CP2 32K / 16 0.000871% 5013.7 → 9353.2 25.530 → 13.685 -46.40% 12.08 → 55.68 16.90 → 61.64
  • Recompute:max-rank allocator 节省 32.88%,HBM 采样峰值从 46.39 降到 34.15 GiB;时延增加 25.70%。
  • Async Offload:allocator 节省 1.35%,HBM 采样峰值不变;耗时差 +0.09%,是单次运行的波动,不代表加速或减速。
  • Ulysses CP2:micro=16 跑满 40 步,但 allocator 峰值从 12.08 升到 55.68 GiB,吞吐下降 46.40%。rank 0/1 日志确认文本从 32768 切成 16384 tokens,视觉 packed 输入也被切分。

6.2 耗时与显存图

两张图只画了开启侧(Recompute on、Offload on、Ulysses CP2),OFF 侧数值见 6.1 表。CP2 与另外两项不在同一组(micro=16 对 micro=64),柱子长度不能直接比较。

P32K 开启侧平均 ms/iter

P32K 开启侧 max-rank allocator 峰值

6.3 Loss 对拍图

展开 Recompute、Offload、Ulysses CP 的 40 步 loss 对拍(以 OFF 为分母)

Recompute off vs on,32K / micro=64

Async Offload off vs on,32K / micro=64

Ulysses CP1 vs CP2,32K / micro=16

6.4 OOM 与运行状态

CP2 容量探针。 在 32K 下,CP2 的 micro=32 和 micro=64 短探针都 NPU OOM,同条件的 CP1 短探针能跑通。异常栈落在 ChunkLoss 的 lm_head 反向阶段,仅凭这一点不能判断那次大额申请是否来自 CP 通信。结论是:CP 数值路径正确,但在这些压力点上没有容量或速度优势。两份 OOM 日志和状态文件已保留。

Offload 正式轮。 日志记录跑满 40/40 步,loss 有限,无 OOM。之后训练容器被替换,没有生成该轮的 status.json,所以退出码未知。6.1 的数值和速度用这份完整的 40 步日志计算,但不把这一轮记为正常退出。Offload 的 12 步显存诊断和 18 步 profiler 都是 exit 0。

6.5 Offload 的搬运与计算交叠

rank 0,step 10–12 Offload 关闭 Offload 开启
显式 D2H host 调用次数 0 9
显式 H2D host 调用次数 0 9
全部设备 PCIE DMA 事件数 18 79
PCIE DMA 累计时长 16.597 ms 245.177 ms
PCIE DMA 与 AI Core/Vector 计算区间交叠 99.95% 73.48%
全部通信时间 / profiler stage 3.67% 3.61%

开启 Offload 后出现了 D2H/H2D,设备时间线上能看到 PCIE DMA 与计算并行。注意交叠率统计的是窗口内全部 PCIE DMA 事件,没有单独追踪 Offload 张量的搬运;关闭时本来就有 PCIE DMA,所以新增的设备时间不能全部算到 Offload 头上。配合 1.35% 的显存收益,目前不能说 Offload 带来了明显的容量提升。

下面三张图对应上表,pressure_base 为 Offload 关闭,pressure_offload_on 为开启。

展开通信时间、通信占比与 PCIE DMA 图

rank 0 通信时间(ms/step)

rank 0 通信占比,对应上表最后一行

3 个采样 step 的 PCIE DMA 累计设备时间,对应上表第 4 行

7. 复现与结果边界

  • 配置、权重转换、训练和导出命令见 README_v1.md,启动脚本为 finetune_glm4_5v_106B_v1.sh。
  • 特性实验用的 runner、探针和日志分析脚本是离线验证材料,没有提交到 PR。
  • F200 / F500 的配置、训练日志、各 rank 显存和 profiler 已归档;P32K 另外保留了校准记录和两份 OOM 日志。
  • 尚未提供:逐步 effective tokens/s、动态 chunk 大小轨迹、只针对 Offload 张量的 DMA 交叠率。本文的 samples/s 和全部 PCIE DMA 统计不能代替这些指标。
  • CP 在压力测试中的表现还需要进一步分析。所有结论都来自微型同构模型,不能外推到 106B 完整模型。

8. 附录:双后端迁移记录(2000 步结果更新)

展开 2000 步对拍配置、量化结果与 5 张更新图片;B/C 组保留历史记录

A 组已替换为 2026-10-11 完成的 8 卡、128 专家、2000 步对拍;复用已完成的 Megatron 基线,pure FSDP2 从对应初始 DCP 重新训练。B/C 组保留早期结果。这些跨后端实验与第 4–6 节的微型模型特性开关实验不同,绝对耗时和显存不能混用。

本次 A 组配置:

  • 硬件为 8 × Ascend 910B3(64 GiB/卡);Python 3.11.14、PyTorch 2.7.1、torch-npu 2.7.1.post8、Transformers 4.57.0。
  • 文本层数 46→4、vision depth→4,保留 128 routed experts、top-k 8;其余模型维度沿用原始配置。不是完整 106B 模型验证。
  • 数据为固定的 2048 条真实 LLaVA/COCO 图文样本;cutoff_len=1024、image_max_pixels=262144、shuffle=false。pure 侧 num_workers=0、enable_preload=false。
  • EP=1、CP=1、FSDP/DP=8;micro batch=1、梯度累积=1、global batch=8;BF16 计算、FP32 梯度归约,pure 参数保留 FP32。两端初始 DCP 的 104 个张量经布局映射后逐元素一致,不恢复 optimizer/RNG。
  • seed=1234;AdamW、lr=1e-5、cosine、2000 步学习率计划、warmup ratio=0.1、weight decay=0、clip grad=0;loss_type=default,ChunkLoss / Offload / EP Balance 关闭。
  • 两端实际 attention 对齐为 SDPA;只冻结 model.visual.patch_embed、model.visual.blocks、model.visual.merger,其余视觉参数仍训练;视觉和文本层均启用 reentrant recompute。pure 的 EP=1 使用 grouped-MoE。
  • 为匹配 Megatron 的 BF16 包装,在独立验证入口中、模型准备后且加载检查点前,将浮点 buffer(含 RoPE inv_freq)转换为 BF16,并同步 original_inv_freq 引用;不转换 FP32 参数或整数 buffer。它是本轮对拍条件,不是默认训练 YAML 自带的行为,也不表示 BF16 RoPE 比 FP32 更准确。

实测代码为 4f997257 加 grouped-MoE 改动及上述独立入口,运行模型文件与后来提交的 ef6cf97a 一致;该文件 SHA-256 为 67a4be854f40a237aa21bb3b0fc9c7b1fd6cc805640ce13e83c71e5f9addb50d。之后 YAML 改名为 glm4_5v_106B_config_v1.yaml,没有因此重跑训练。配置与 buffer 前处理代码见 PR !2875 的本轮对拍说明。

B/C 组的早期配置保持原记录:约 2.57B 参数的同构减层模型,文本层数 46→4、routed experts 128→8、top-8→top-2、vision depth→4;hidden size、heads、head dim、RoPE 和词表保持原值。两个后端的 token 流、loss_type=default、冻结方式、seed 和超参一致。

精度与性能

下表的 A 是本次 2000 步结果,B/C 是保留的历史组名,和第 3.2 节的配置 B 无关。

组别 硬件与数据 步数 loss 平均相对误差 最大相对误差
A(2026-10-11) 8 × Ascend 910B3,2048 条真实图文样本,128 专家 / top-k 8 2000 1.617965% 14.324236%
B Ascend 910B3 单卡,512 条真实图文样本 300 0.152% 0.615%
C Ascend 910B3 单卡,16 条纯文本样本 30 0.394% 3.6%

A 组按 mean(abs(pure_loss-megatron_loss)/(abs(megatron_loss)+1e-8)) × 100% 计算全部 2000 个相同步号,不丢弃尖峰或后段;TrainingLogParser 与独立日志计算均为 1.617965%。最大单步误差为 14.324236%,所以通过的是全程平均误差 <2%,不是每步都小于 2%。两端步号完整、学习率逐步一致,loss/grad norm 为有限值,pure 训练正常退出(exit 0)。

A 组 grad norm 平均相对误差为 2.880600%,最大为 89.381628%;该指标取自保留三位小数的训练日志,不等于逐参数梯度检查,也不使用 loss 的 2% 验收线。Megatron − pure 的有符号 loss 差均值为 −0.000321705475,平均绝对差为 0.005527924135。

C 组末期 loss 已降到约 1e-4,相对误差容易被小分母放大,只作冒烟参考。

组别 Megatron-FSDP2 ms/iter 纯 FSDP2 ms/iter 相对吞吐
A(2026-10-11) 922.725 903.014 1.0218×
B 336.0 322.9 1.041×

A 组两端均完成 2000 步。该组为 8 卡、文本/视觉各 4 层、128 专家、top-k 8、EP=1;BF16 计算、FP32 reduction、SDPA、冻结范围与重计算按上面的配置对齐。

A 组性能指标 Megatron-FSDP2 纯 FSDP2
平均每步耗时 922.725 ms 903.014 ms
吞吐 8.670 samples/s 8.859 samples/s
P95 每步耗时 921.5 ms 912.5 ms
P99 每步耗时 1125.4 ms 918.9 ms

纯 FSDP2 的平均每步耗时降低 2.14%,吞吐提高 2.18%:本次实测与 Megatron-FSDP2 基本持平、略快,满足该测试配置下“不低于 Megatron”的性能要求;同时,全程平均 loss 相对误差为 1.618%。

这是单次、减层配置的结果,约 2% 的差异不能视为已证明的稳定加速,也不能外推到完整 106B 模型、EP>1 或多种子运行。

B 组沿用早期性能记录:两侧精度设置不同(基线 fp32,本实现 bf16 / fp32 reduction),attention 实现也不同(SDPA / Flash Attention 2),所以不能据此判断两个后端性能相当,也不能代表 106B 完整模型。

保留的早期特性状态与前置验证(非本轮 2000 步)

  • 融合 RMSNorm / RoPE 开启;单卡 EP=1,未启用跨卡融合 MoE。
  • 当时 ChunkLoss 配置实际没有生效,两侧都走普通 loss,这批数字不含 ChunkLoss 收益。第 4 节的 ChunkLoss 显存数据来自后来的独立测试。
  • 重计算和 Offload 关闭,峰值约 27 GB / 64 GB。
验证项 结果
DCP 与 HF 两条加载链路 确定性模式、相同 seed,各 30 步,逐步 loss 一致
EP2 与 EP1 4 卡、相同 seed,各 30 步;首步相对差 4e-5,loss > 0.1 区间 3–4 位有效数字一致
双后端 token 流 前 8 个 batch 的 input_ids、labels、loss_mask 逐位一致

本轮 2000 步对照图片

训练日志:以下两图从本次对照所用的原始日志中截取 checkpoint 加载、首 3 步和末 3 步,时间戳原样保留,不是重新执行的终端截图。

Megatron-FSDP2:128 专家、2000 步原始日志摘录

pure FSDP2:128 专家、2000 步原始日志摘录

双后端对拍:TrainingLogParser 直接读取原始日志,Comparison step=1,不平滑;横轴 0 对应 step 1,相对误差以 Megatron 为分母。红线 0.02 仅为 2% 参照;验收针对全程平均 loss 相对误差,不针对逐步 loss 或 grad norm。

Loss:2000 步双后端曲线与相对误差

Grad norm:2000 步双后端曲线与相对误差

Comparison normal:2000 步 Megatron − pure 有符号 loss 差值

当时用到的 compare_runs.py、verify_expert_layout.py 是离线验证工具,不是当前 PR 的可运行入口。

likedislike
yeqm成员
8月21日 评论:

👋 您好,欢迎向 MindSpeed MM 提交 Issue!
我们已收到您的反馈,感谢你对开源社区的支持。🎉
📅 处理时效: 维护团队将在 24 小时内 查看并回复您的问题(工作日)。
🚨 紧急联系: 如果您的问题非常紧急,可通过微信联系我们。
请确保 Issue 描述清晰,包含复现步骤和日志,这将帮助我们更快定位问题。谢谢!

likedislike
且奏长歌且奏长歌成员
28 天前 issue状态由 TODO 改变为 DONE
且奏长歌且奏长歌成员
28 天前 关闭了 issue
ascend-robotascend-robot成员
28 天前 添加了label:resolved
SSuperKoalaKing
20 天前 修改了issue 的描述
SSuperKoalaKing
20 天前 修改了issue 的描述
SSuperKoalaKing
19 天前 修改了issue 的描述
SSuperKoalaKing
3 天前 修改了issue 的描述
SSuperKoalaKing
3 天前 修改了issue 的描述
SSuperKoalaKing
3 天前 修改了issue 的描述
SSuperKoalaKing
3 天前 修改了issue 的描述