Bit-exact 训练要保证什么?
nondeterminism 从哪来,为什么值得付 overhead?
先弄清楚:每个概念是什么
- Bitwise determinism
- 两次 run 每一步的结果每个 bit 都相同,不是 loss 看起来差不多。
- Fixed environment
- 保证的前提。tracker 要求 model、data、seed、software、hardware class 和 topology 都相同,换了卡数或并行配置就不在保证里。
- Reduction order
- 很多数相加时先加谁后加谁。浮点加法每一步都要舍入,顺序一变末位就可能变。ring 和 tree 的次序见 all-reduce。
- Autotuning
- 运行时试几种 kernel 配置,挑最快的用。两次挑的不一样,bit 就可能不一样。
看图:同样四个数,两种加法顺序
30 秒回答
Bitwise determinism means two runs in the same fixed environment, with the same model, data, seed, software, hardware and topology, produce identical bits at every step, and a resumed run matches the uninterrupted one. Nondeterminism comes from floating-point reduction order and from autotuning that picks different kernels. The tracker has three gates: repeatability, baseline equivalence and restart replay. You verify with tensor hashes, not printed loss. It's worth the cost because you can replay a loss spike and change one thing at a time. The target is under ten percent step-time overhead; NVIDIA's blog reports about two percent on Nemotron.
Nondeterminism 从哪来
| 来源 | 出处里的例子 | 修法 |
|---|---|---|
| Reduction order 随 topology 变 | tracker 在 Nemotron-3 Ultra 上找到的第一类:final gradient reduction 的结果依赖 topology | blog 的通用修法是换成 deterministic reduction;tracker 写这一条的 fix 还在 review |
| Autotuning | tracker 的第二类:外部 Mamba kernel 的 Triton autotuning | 把选好的配置 pin 住或 cache 下来(blog) |
| 多个 writer 写同一个地址 | blog:grouped-GEMM 的 epilogue 里几个 N-tile 累加到同一个地址,结果取决于谁先到 | 每个 writer 一个 private slot,写完按固定顺序合并 |
怎么验证:三个 gate
- Fixed-environment repeatability:同一个 fixed environment 跑两次,training metrics 和 trace event 要 bit-exact
- Baseline equivalence:一个优化自己可重复还不够,还要和已有的 deterministic baseline 比
- Restart replay:从 checkpoint 恢复的 run,要和不中断的 run 从那一步起一致
打印的 loss 不够灵敏,两次 run 的 loss 一样时 gradient 的低位仍可能不同。blog 的做法是每步给选定的 metric 和 tensor 算 fingerprint,用 torch.hash_tensor,最后逐 byte 比较。
为什么值得付 overhead
- Debug:loss spike 能在同一步重现,再一次只换一个组件来定位(blog)
- RL:training 和 generation 可以用不同的 EP size,这比 fixed environment 的保证更强。PR #8261 在 Nemotron-3-Nano 上量到一层 MoE 在 EP2 和 EP1 之间有 98% 的 token 不同,每个元素差约 1 ulp;EP2 训练、EP1 生成时 sampled token 的 log-prob 最多差 0.89。修法是一个 opt-in 的 flag,让每个 EP size 走同一棵 fp32 reduction tree
tracker 的目标是 "less than 10% steady-state step-time overhead",stretch 目标约 5%。blog 的实测是 Nemotron 3 Ultra 从约 17% 降到 2%,在 3,072 GPU 上是 1.5%。另一个大规模 Nemotron recipe 在 2,432 GPU 上约 2%,800 步内保持 bitwise 一致。blog 的算例是 100 天、10,000 GPU 的训练,overhead 从 15% 降到 5% 省 10 天,即 100,000 GPU-days。
必答点
- bit-exact 指每一步每个 bit 相同,前提是 fixed environment,topology 也算在内
- 浮点加法不满足结合律,reduction order 一变末位就变
- tracker 记的两类来源:依赖 topology 的 gradient reduction,Triton autotuning
- 三个 gate:repeatability、baseline equivalence、restart replay
- 验证看 tensor 的 hash,不看打印的 loss
- 目标 overhead 低于 10%,stretch 约 5%;blog 在 Nemotron 上报约 2%
追问
开了 deterministic 为什么会慢?overhead 怎么压下来?
让并发的 writer 串行能恢复 determinism,但丢了并行度,blog 改成 private slot 后 kernel 内部照样并行。tracker 还记了关掉 torch.utils.deterministic.fill_uninitialized_memory 后结果仍然 bit-exact,steady-state 性能在两个模型上提高约 16% 和 18%。
小规模没问题,大规模才出现 nondeterminism,怎么查?
blog 给的原因是随规模变的 communication 或 expert-parallel 路径。做法是逐步加规模,trace 选定的 rank,找到第一个随规模变的 operation,PR #7262 的 workflow 按 rank 记录有序的 tensor fingerprint 供离线比较。
deterministic mode 下有什么不能用?
--deterministic-mode 会设好环境、打开 PyTorch 的 deterministic algorithms,并拒绝没有 deterministic 路径的功能(blog)。tracker 写 --moe-router-fusion 自己可重复,但会改变已有的 deterministic baseline,所以还不算保持 baseline 的优化。
来源determinism tracker #5785(目标、三个 gate、两类来源、fill_uninitialized_memory)· NVIDIA blog:Scale Bitwise-Deterministic Pretraining with NVIDIA Megatron Core(两条保证、overhead 实测、Table 2、grouped-GEMM 的例子、fingerprint)· core 0.20.0 release notes · PR #8261 和重新合入的 PR #9107(EP-size-invariant expert combine)· PR #8458(PR 模板的 determinism checklist)· Q4 roadmap #9232 · ml-八股 06 第零节 · 全部原话见 更新笔记 3.2、3.4 节