[PyTorch] Schedule delayed-scaling updates after backward - #3456
Open
pggPL wants to merge 14 commits into
Open
Conversation
Keep FP8GlobalStateManager responsible for iterating registered delayed-scaling buckets, while RecipeState subclasses define the corresponding update algorithm. Extract recipe-to-state dispatch so construction and global updates share one mapping. Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
Queue one quantization state update at the autograd boundary instead of assigning it to the first FP8 module seen in forward. Add an optional logical-backward scope for multi-backward schedules and delayed weight-gradient computation. Co-authored-by: AlbertYang514 <201034045+AlbertYang514@users.noreply.github.com> Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
Document that graphs produced under one autocast need an explicit logical-backward scope when their backward calls should share one delayed-scaling update. Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
for more information, see https://pre-commit.ci
Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
…pe always update Modules call FP8GlobalStateManager.request_backward_quantization_update(recipe) from backward whenever they ran in FP8; the recipe and graph-capture checks live in that helper instead of being repeated per module. quantization_backward_scope now marks the update pending on entry, so ranks that ran no quantized backward inside the scope still join the amax reduction. Add a distributed test covering a module skipped on some ranks and a rank with no backward inside the scope. Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
Decide in forward via FP8GlobalStateManager.backward_quantization_update_needed() and carry only a bool through ctx; request_backward_quantization_update() takes no arguments. Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
…lobal state in distributed test Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
…test_numerics.py Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
…ture page Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
Gradient quantization happens in backward(); backward_dw() only runs the stored GEMM, so it does not motivate the scope. Signed-off-by: Pawel Gadzinski <pgadzinski@nvidia.com>
pggPL
marked this pull request as ready for review
September 2, 2026 12:37
Contributor
Greptile SummaryThis PR moves delayed-scaling gradient amax and scale updates from backward traversal order to an end-of-autograd-task callback, and introduces a public scope for grouping multiple backward calls.
Confidence Score: 5/5The PR appears safe to merge with no concrete blocking or non-blocking defects identified. The callback scheduler, recipe-state delegation, module integrations, checkpoint handling, public scope, and distributed participation behavior are internally consistent and covered across the major changed execution paths. Important Files Changed
Sequence DiagramsequenceDiagram
participant App
participant Module
participant Autograd
participant Manager as FP8GlobalStateManager
participant Recipe as RecipeState
App->>Module: Quantized forward
Module->>Module: Save update-needed flag
App->>Autograd: backward()
Autograd->>Module: Module backward
Module->>Manager: Request backward quantization update
Manager->>Autograd: Queue one GraphTask callback
Autograd-->>Manager: Run callback after task completes
Manager->>Recipe: Reduce gradient amaxes and update scales
opt Multiple backward calls
App->>Manager: Enter quantization_backward_scope
App->>Autograd: backward() per microbatch
Manager->>Manager: Defer pending update
App->>Manager: Exit outermost scope
Manager->>Recipe: Run one logical-backward update
end
Reviews (1): Last reviewed commit: "docs: drop backward_dw from the quantiza..." | Re-trigger Greptile |
This was referenced Sep 2, 2026
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.
Description
Delayed-scaling (amax/scale) updates are currently owned by the first FP8 module seen in forward and executed from that module's backward. This depends on backward traversal order and breaks with unused branches, reentrant checkpointing, or schedules that delay weight-gradient computation.
This PR moves the update to the end of the autograd task instead. Each participating module requests an update and TE queues a single callback on the enclosing
GraphTask, so the update runs once after the whole backward has finished. Reentrant TE checkpointing registers the callback on the outer task before entering its nested backward.Plain
.backward()needs no changes. A newquantization_backward_scope()lets applications define a larger logical backward, so the update runs once when the outermost scope exits:The update always runs on scope exit, even on ranks that ran no quantized backward inside it, so every rank joins the amax reduction. Like
autocast, the scope must be entered and exited on all ranks.New API
transformer_engine.pytorch.quantization_backward_scope()(context manager, documented in the PyTorch API reference and on the delayed scaling feature page):autocast, it must be entered and exited on all ranks.Internal hooks used by the modules:
FP8GlobalStateManager.backward_quantization_update_needed()(decided in forward, stored as a bool on the autograd ctx) andFP8GlobalStateManager.request_backward_quantization_update()(called from backward, queues one callback per autograd task).Type of change
Changes
RecipeState.backward_quantization_update_needed()), carry only a bool through the autograd ctx, and request from backward withrequest_backward_quantization_update().GraphTask.quantization_backward_scope()for custom logical-backward boundaries; it always updates on exit.reduce_and_update_fp8_tensorsalias working.Checklist: