perf(megatron): defer loss all-reduce to log time - #9966
Open
gakkiri wants to merge 2 commits into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Defer logging-loss DP×CP all-reduce to log time
PR type
PR information
Summary
MegatronTrainer.loss_funccurrently performs one DP×CP all-reduce per microbatch for the detached logging loss. This PR keeps the local[loss_sum, token_count]pair during forward/backward aggregation and performs the reduction once per logging event.This only changes the logging path. Training math is unchanged, and the reported loss remains mathematically equivalent, modulo floating-point reduction-order differences.
Motivation
The current causal-LM path runs this synchronous collective once per microbatch:
The reduced tensor feeds only
metrics['loss']:lm_loss, returned separately;_aggregated_metricssubsequently sums the[loss_sum, token_count]pairs over microbatches and logging steps.Although the payload is only two float32 values, each call creates a synchronization point across the participating DP×CP group. On a large, latency-sensitive group, per-microbatch rank jitter can therefore be exposed repeatedly on the training critical path.
The change
Only
swift/megatron/trainers/trainer.pyis changed:loss_funcreturns its local detached[loss_sum, token_count]without immediately reducing it.MegatronTrainer._log_callbackreduces the aggregated pair overget_data_parallel_group(with_context_parallel=True)before the base callback converts it tosum / count.losskey because its entire logging window contained zero valid tokens, it contributes[0, 0]. If the group-global count is also zero, the key is dropped, matching the previous behavior.The override is limited to
MegatronTrainerwithtask_type == 'causal_lm'.BaseMegatronTraineris not changed because it is also shared by DPO, GRPO, Reward, Embedding, and other trainers that already reduce their own metrics. The seq-cls path is also unchanged.With
enable_channel_loss=true, per-channel metrics still perform their existing per-microbatchall_gather_objectand all-reduce. Deferring that dynamic-key path is outside the scope of this PR.Why the result is equivalent
For a logging window containing
Koptimizer steps andMmicrobatches per step, letx[t,m]be one rank's local[loss_sum, token_count]pair. The old and new paths are mathematically equivalent because all-reduce(SUM) is linear:The number of logging-loss collectives per logging window changes from
K × Mto1, savingK × M - 1calls. The final quotient is the same global token-weighted mean. Floating-point addition occurs in a different order, so last-bit differences are possible and expected.Collective participation remains consistent:
losskey exists.Experiment results
Environment
98a09c18c; the patch applies cleanly to the tag), Megatron Core 0.18.0, torch 2.8.0+cu128, NCCL 2.27.3, DeepEP 1.2.1+9af0e0d, TransformerEngine 2.16.1, Python 3.12.13, CUDA 12.9, driver 535.247.01.enable_channel_loss=false.2048 / (2 × 128) = 8per optimizer step. Each step in the two-step profiler window contained a logging event, so this path changes from 8 Python all-reduce invocations per step to 1.Profiler observations
torch.profilertraces were captured for ranks 0–7 over two-step windows. The table reports trace-level stall observations associated with the reporting-loss all-reduce; profiler kernel-event counts are intentionally omitted because a kernel-event count is not necessarily one-to-one with Python collective invocations.Step time
Controlled A/B runs used the same steps, data order, hardware, and
enable_channel_loss=false. Over steps 6–14 (n=9):The observed gain is specific to this latency-sensitive cluster and workload. Lower-latency fabrics, smaller DP×CP groups, or lower inter-rank variance should show a smaller absolute improvement.
Correctness validation
MegatronTrainer._log_callback, including thesuper()chain.rtol=1e-6.losskey still entered the collective without hanging, and both ranks logged the correct global mean.2.57292247and2.57282043; the patched run produced2.57309008. All differences areO(1e-4)absolute, consistent in scale with expected nondeterministic variation. Step-1 loss was bit-identical across all three (2.33354068), and no anomalous grad-norm or downstream-training divergence was observed. The deterministic two-rank test above is the direct equivalence check.git apply --checkon a fresh v4.4.1 checkout and contains only this change.Expected benefit
The benefit should be largest with:
The benefit should be smaller when the DP×CP group is small, the fabric is low-latency, or both
num_microbatchesandlogging_stepsare 1. No regression was observed in the tested configurations; the new path replaces many per-microbatch synchronization points with one two-element collective per logging event.Summary
This PR moves a detached, logging-only DP×CP all-reduce out of the per-microbatch critical path. It reduces the logging-loss collective count from
num_microbatches × logging_stepsper logging window to one, preserves the global token-weighted loss up to floating-point reduction-order effects, handles zero-token CP shards without collective mismatch, and reduced mean step time by 19.6% in the measured DP128 workload.