perf(training): synchronize keypoint DDP once per optimizer step - #1443
Open
JESUSROYETH wants to merge 1 commit into
Open
perf(training): synchronize keypoint DDP once per optimizer step#1443JESUSROYETH wants to merge 1 commit into
JESUSROYETH wants to merge 1 commit into
Conversation
JESUSROYETH
requested review from
Borda,
SkalskiP,
isaacrob and
probicheaux
as code owners
September 8, 2026 21:27
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #1443 +/- ##
=======================================
Coverage 87% 87%
=======================================
Files 117 117
Lines 15260 15264 +4
=======================================
+ Hits 13214 13218 +4
Misses 2046 2046 🚀 New features to boost your workflow:
|
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.
What is wrong
Keypoint training uses manual optimization to normalise the loss over the full accumulated box count. Under DDP,
manual_backward()currently runs with gradient synchronisation enabled on every microbatch, then_should_step_optimizer()decides if the optimizer can step. So withgrad_accum_steps=4, each accumulation window performs four gradient reductions when one is enough.This is also the limitation documented when keypoint DDP support landed in #1232, and it is the DDP training question left open in #1410.
What changes
The backward pass now uses Lightning's own
LightningOptimizer.toggle_model(sync_grad=...)context. Intermediate microbatches run under DDPno_sync(), while the backward that closes a full or partial accumulation window synchronises the accumulated gradient before the optimizer step.There is no new option or fallback. Detection and segmentation keep the automatic-optimization path, and
grad_accum_steps=1still synchronises every backward. The warning inbuild_trainer()and the multi-GPU training note are updated to match the new behaviour.Two-L4 result
Measured with
RFDETRKeypointPreviewon real COCO 2017 person-keypoint images, two NVIDIA L4 GPUs, BF16, batch size 1 per rank, two-rank NCCL DDP,grad_accum_steps=4, torch 2.10.0+cu130 / CUDA 13.0 / driver 580.173.02. Each trial ran 64 microbatches per rank, discarded the first 8 and timed the remaining 56 withtorch.cuda.synchronize()at both boundaries. The arms were counterbalanced.Trainer.fitsecondsAll ten performance trials completed and the steady-state ranges do not overlap.
Correctness and validation
The new parametrised test covers the three synchronisation decisions: an intermediate microbatch, a complete accumulation window, and the partial final-window flush. It failed on
developbecausetoggle_model()was never called, then passed with the change. The existing large-effective-batch tests continue to check the accumulated gradient against one large batch across six box-count/accumulation cases.A deterministic two-device
Trainer.fitcheck also ran two optimizer steps with exactly representable float64 gradients. Two baseline and two candidate runs produced the same parameter bytes (bfaed4915cfeef3f). The real model's full state was not bitwise repeatable even baseline against itself, so I am not using that noisy comparison as a parity claim ..pytest tests/training/test_module_model.py -q: 197 passed, 1 skippedpre-commit run --all-files: all hooks passedThis does not include training to convergence or an mAP claim. It also does not generalise the 5.06% number beyond two L4 GPUs and
grad_accum_steps=4; more GPUs, multi-node DDP and other interconnects were not measured.