[tools] Report paired numerical-diff statistics in loss_compare.py - #4393
[tools] Report paired numerical-diff statistics in loss_compare.py#4393yuweih205 wants to merge 1 commit into
Conversation
|
Hi @yuweih205! Thank you for your pull request and welcome to our community. Action RequiredIn order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you. ProcessIn order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA. Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks! |
|
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks! |
Summary
loss_compare.pycurrently prints per-step differences and separate per-run averages, but it does not report paired statistics over the common steps. This makes it difficult to identify when a comparison first diverges or how large the trajectory drift is. For example, an overall average difference can round to zero while individual steps still mismatch.This PR adds a reusable
compare_series()helper and reports paired statistics for every selected metric, includinglossandgrad_norm:The comparator is injectable so a future tolerance policy can reuse the same statistics path without introducing a second comparison implementation.
Motivation: observed numerical-alignment mismatch
This is motivated by an observed precision/trajectory mismatch, not only by a reporting-formatting gap. In a controlled Qwen3-235B-A22B comparison with the same initial checkpoint, data order,
seed=42, and deterministic execution, old TorchTitan and currentmainboth completed 1,000 steps but showed:grad_normdivergence beginning at step 19;0.04191409;0.12922001;7.260471(main) vs.7.174619(old), a difference of about0.085853.The controlled ablations show that this is a measurable numerical mismatch and that specific MoE changes account for different parts of the observed trajectory change:
grad_normmain0.04191409; max abs diff:0.12922001; final diff: about0.0858530.10892582at step 9555.3125at step 7201.43051e-4at step 420.1251000/1000bitwise exact1000/1000bitwise exactIn the combined-ablation run, the final loss was
7.174618721008301on both sides and the finalgrad_normwas1.046875on both sides; batch fingerprints also matched for all 1,000 steps. These results are from the controlled experiment documented in the linked discussion and are included here to explain the need for paired reporting, not as a claim that this PR diagnoses the underlying model changes or proves that final convergence quality is worse.The related expert-bias semantics and migration questions are tracked separately in #4394. This is also consistent with the issue discussed in #3996, where concrete step mismatches were visible even though the reported average difference was
0.000000.Additional evidence: the largest drift is a composite path
The largest loss difference in the experiment log comes from a combination of modern implementation choices, rather than from one isolated change. In a Qwen3-235B-A22B comparison,
FlexAttention + fused QKV + ChunkedLossversusSDPA + unfused QKV + ordinary CEproduced the following result over 200 paired steps:grad_normexact0.2192220.6652821/200The same experiment notes also contain a 524-step summary for this modern-vs.-SDPA family (
0.12834MAE and0.66528maximum difference). Because the paired windows differ, these summaries should not be combined into one statistic. An earlier 100-step Llama3-8B comparison likewise reported0.04387MAE and a0.22112maximum difference at step 71.The documented aligned fallback supports the following limited statement: in the aligned dense-model comparison, replacing the three modern choices with
SDPA + unfused QKV + ordinary CErestored bitwise overlap. This is a composite reversion, not proof that each of #3571, #2878, and #2937 independently accounts for the full0.665282drift. For the Qwen3 MoE 1,000-step bitwise closure shown above, exactness was instead obtained by disabling #3386 and #3666 while already usingFA3 + unfused QKV + plain CE; it should not be described as “reverting the three dense-path changes alone fixes the MoE mismatch.”The available per-feature measurements are useful for sizing individual effects, but they are not a complete
2^3factorial design or three strict one-at-a-time removals from the 200-step modern baseline:FA3 + fused QKV + CE0.00016330.00085160.0002239FA3 + unfused QKV + ChunkedLoss0.00020680.00100040.0002925FA3 + fused QKV + ChunkedLoss0.00017070.00088690.00021980.002220.03046The first three rows are the feature-level matrix reported in the experiment notes (the corresponding runs were not all successful through the same final step), and the last row uses an older TorchTitan comparison. These numbers therefore should be read as per-path diagnostics, not as additive causal contributions to
0.665282.Example output:
--assert-equalremains exact by default; no training logic or tolerance flag is changed.Test plan
python3 -m unittest tests.unit_tests.cpu.test_loss_compare_statistics -v(7 tests)python3 -m py_compile scripts/loss_compare.py tests/unit_tests/cpu/test_loss_compare_statistics.pygit diff --checkRelated context
This PR is complementary to the existing relative-tolerance work in #3847: it does not add another
--rtolimplementation.