已关闭
【实践文档】:glm4.5v迁移纯FSDP2性能优化文档 #562
SuperKoalaKing创建于 8月4日关闭于 28 天前
yeqm
8月21日 评论:
8月21日 评论:
👋 您好,欢迎向 MindSpeed MM 提交 Issue!
我们已收到您的反馈,感谢你对开源社区的支持。🎉
📅 处理时效: 维护团队将在 24 小时内 查看并回复您的问题(工作日)。
🚨 紧急联系: 如果您的问题非常紧急,可通过微信联系我们。
请确保 Issue 描述清晰,包含复现步骤和日志,这将帮助我们更快定位问题。谢谢!


28 天前 issue状态由 TODO 改变为 DONE
28 天前 关闭了 issue
28 天前 添加了label:resolved
20 天前 修改了issue 的描述
20 天前 修改了issue 的描述
19 天前 修改了issue 的描述
3 天前 修改了issue 的描述
3 天前 修改了issue 的描述
3 天前 修改了issue 的描述
3 天前 修改了issue 的描述
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)。下表只列性能和显存。
2. 适配内容
GLM4V_DCP_3D=1选择 3D 布局模型代码在
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 实验分组
只在同组内比较 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 的完整配置
GLM-4.5V-tiny-dcp微型检查点,8 个 routed experts、8 个 attention heads。compare_data/data.json,2048 个图文样本,cutoff_len=1024,shuffle=false。cutoff 是上限,样本实际长度不一。展开 P32K 的模型、数据构造与采样说明
max_position_embeddings=4096,本次只在隔离的 HF/DCP 副本中改为 32768;所有非配置文件逐个核对 SHA-256 一致,原权重未改。扩大位置上限只用于容量和速度压力测试,不代表长上下文语义质量。npu-smiHBM 在同一个 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 节表格的"配置"列给出两者的对应关系。
3.3 指标定义
mean(abs(test-reference)/(abs(reference)+1e-8)) × 100%,按相同步数逐项对齐。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 峰值的平均值。4. F200:单项特性对拍
4.1 精度与耗时
左侧为 OFF(reference),右侧为 ON(test)。
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。
展开各配置相对 B 的误差、grad norm 与 P95/P99
Grad norm 取自训练日志(保留三位小数),不是逐参数的梯度检查。每个配置只跑了一次。
展开 8 张 loss 对拍图(每张 200 步)
读图说明:
loss:,Comparison step=1,不平滑),横轴 0 对应 step 1。CP 与 EP
ChunkLoss
Recompute、Offload 与 EP Balance
4.2 逐 rank 峰值显存
单位 GiB,统计 30 步内的 allocator allocated 峰值,不是设备总占用。
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)。
4.3 EP Balance 的负载与守恒
EP 负载探针单独跑 30 步,开关两侧各采集 120 次 dispatcher 调用。Workload 是本 rank 专家分到的 assignment 数之和,包含 top-k 重复和重计算产生的重复调用,不等于有效 token 数。
开启 Balance 后,120 次调用中每次的跨 rank 总 assignment 数都与关闭时一致,且 8 个 rank 分到的数量相等。负载均衡生效了,但 4.1 的性能轮里没有因此加速。探针本身带额外的 collective,其耗时不计入性能数据。
4.4 Profiler:通信与 Offload
采集 rank 0 的 step 20–24。这里的时间只用于看通信构成,不替代 4.1 的性能数据。
各特性的特征通信(5 步累计):
各操作的 elapsed 之和不等于未重叠的墙钟时间。
Offload。 启动日志确认卸载覆盖
model.visual.blocks.0/1和model.language_model.layers.0/1,对照两侧的 recompute 设置相同。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 步下重跑一次作对照。
两种组合都跑满 500 步,相对 B 的 loss 平均相对误差为 0.000422% 和 0.000383%。08、09、10 的 P99 有明显长尾,表中保留实测值。
展开 3 张 500 步 loss 对拍图(读法同 4.1)
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 结果
6.2 耗时与显存图
两张图只画了开启侧(Recompute on、Offload on、Ulysses CP2),OFF 侧数值见 6.1 表。CP2 与另外两项不在同一组(micro=16 对 micro=64),柱子长度不能直接比较。
6.3 Loss 对拍图
展开 Recompute、Offload、Ulysses CP 的 40 步 loss 对拍(以 OFF 为分母)
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 的搬运与计算交叠
开启 Offload 后出现了 D2H/H2D,设备时间线上能看到 PCIE DMA 与计算并行。注意交叠率统计的是窗口内全部 PCIE DMA 事件,没有单独追踪 Offload 张量的搬运;关闭时本来就有 PCIE DMA,所以新增的设备时间不能全部算到 Offload 头上。配合 1.35% 的显存收益,目前不能说 Offload 带来了明显的容量提升。
下面三张图对应上表,pressure_base 为 Offload 关闭,pressure_offload_on 为开启。
展开通信时间、通信占比与 PCIE DMA 图
7. 复现与结果边界
finetune_glm4_5v_106B_v1.sh。8. 附录:双后端迁移记录(2000 步结果更新)
展开 2000 步对拍配置、量化结果与 5 张更新图片;B/C 组保留历史记录
A 组已替换为 2026-10-11 完成的 8 卡、128 专家、2000 步对拍;复用已完成的 Megatron 基线,pure FSDP2 从对应初始 DCP 重新训练。B/C 组保留早期结果。这些跨后端实验与第 4–6 节的微型模型特性开关实验不同,绝对耗时和显存不能混用。
本次 A 组配置:
model.visual.patch_embed、model.visual.blocks、model.visual.merger,其余视觉参数仍训练;视觉和文本层均启用 reentrant recompute。pure 的 EP=1 使用 grouped-MoE。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 无关。
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,相对误差容易被小分母放大,只作冒烟参考。
A 组两端均完成 2000 步。该组为 8 卡、文本/视觉各 4 层、128 专家、top-k 8、EP=1;BF16 计算、FP32 reduction、SDPA、冻结范围与重计算按上面的配置对齐。
纯 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 步)
本轮 2000 步对照图片
训练日志:以下两图从本次对照所用的原始日志中截取 checkpoint 加载、首 3 步和末 3 步,时间戳原样保留,不是重新执行的终端截图。
双后端对拍:TrainingLogParser 直接读取原始日志,Comparison step=1,不平滑;横轴 0 对应 step 1,相对误差以 Megatron 为分母。红线 0.02 仅为 2% 参照;验收针对全程平均 loss 相对误差,不针对逐步 loss 或 grad norm。
当时用到的
compare_runs.py、verify_expert_layout.py是离线验证工具,不是当前 PR 的可运行入口。