Skip to content

[PyTorch] Keep DistributedWeight objects on ctx across saved-tensor hooks - #3545

Open
xrennvidia wants to merge 2 commits into
NVIDIA:mainfrom
xrennvidia:xren/dist-weight-saved-tensor-hooks
Open

xrennvidia wants to merge 2 commits into
NVIDIA:mainfrom
xrennvidia:xren/dist-weight-saved-tensor-hooks

Conversation

@xrennvidia

@xrennvidia xrennvidia commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

Description

_Linear and _GroupedLinear save the DistributedWeight parameter itself for
backward and gate their distributed-weight path on getting that object back
(is_distributed_weight(saved_weight)). That holds only while no
torch.autograd.graph.saved_tensors_hooks are installed: with hooks active,
SavedVariable::unpack rebuilds a fresh plain tensor from the unpack hook's
result, dropping the Python subclass and its is_distributed_weight marker.
The backward then takes the plain-parameter branch, whose weakrefs point at
the transient all-gathered weights, and fails with
"weight was removed while fuse_wgrad_accumulation=True".

Seen with Megatron-Core fine-grained activation offloading (which installs
such hooks around expert fc1/act) on bf16 GTP-sharded GroupedLinear experts.
Quantized weights were unaffected because their storage objects already stay
on ctx via prepare_for_saving/restore_from_saved, and the op-fuser path reads
the module's own weight attribute instead of the saved tensor.

Keep the DistributedWeight objects as ordinary ctx / LinearBwdArgs references
and prefer them over the saved tensors in backward.

Type of change

  • Documentation change (change only to the documentation, either a fix or a new content)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Infra/Build change
  • Code refactoring

Changes

Please list the changes introduced in this PR:

  • Change A
  • Change B

Checklist:

  • I have read and followed the contributing guidelines
  • The functionality is complete
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

@github-actions github-actions Bot added the community-contribution PRs from external contributor outside the core maintainers, representing community-driven work. label Sep 18, 2026
@greptile-apps

greptile-apps Bot commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge, with the previous request for hook regression coverage fully addressed and manually resolved.

Summary

This PR preserves DistributedWeight Python objects across saved-tensor hooks so Linear and GroupedLinear backward passes continue using the distributed-weight path.

  • Stores strong references to distributed weights outside save_for_backward.
  • Prefers those references during backward before clearing them.
  • Adds CUDA regression coverage for hooked and unhooked execution with fused and unfused weight-gradient accumulation.
  • Registers the new regression suite in the PyTorch L0 test runner.

Diagram

sequenceDiagram
    participant Caller
    participant Forward
    participant Autograd
    participant Hooks as Saved-tensor hooks
    participant Backward
    participant DW as DistributedWeight

    Caller->>Forward: Run Linear / GroupedLinear
    Forward->>DW: Materialize weights for forward
    Forward->>Autograd: Save tensors
    Forward->>Forward: Keep original DistributedWeight reference
    Autograd->>Hooks: Pack and unpack saved tensors
    Hooks-->>Autograd: Return plain Tensor alias
    Autograd->>Backward: Invoke backward
    Backward->>Backward: Prefer retained DistributedWeight
    Backward->>DW: Materialize weights for backward
    Backward->>DW: Finalize distributed gradients
Loading

Reviews (3) · Last reviewed commit: "[PyTorch] Test DistributedWeight dispatc..."

Comment thread transformer_engine/pytorch/module/grouped_linear.py
xrennvidia and others added 2 commits September 18, 2026 02:16
…ooks

_Linear and _GroupedLinear save the DistributedWeight parameter itself for
backward and gate their distributed-weight path on getting that object back
(is_distributed_weight(saved_weight)). That holds only while no
torch.autograd.graph.saved_tensors_hooks are installed: with hooks active,
SavedVariable::unpack rebuilds a fresh plain tensor from the unpack hook's
result, dropping the Python subclass and its is_distributed_weight marker.
The backward then takes the plain-parameter branch, whose weakrefs point at
the transient all-gathered weights, and fails with
"weight was removed while fuse_wgrad_accumulation=True".

Seen with Megatron-Core fine-grained activation offloading (which installs
such hooks around expert fc1/act) on bf16 GTP-sharded GroupedLinear experts.
Quantized weights were unaffected because their storage objects already stay
on ctx via prepare_for_saving/restore_from_saved, and the op-fuser path reads
the module's own weight attribute instead of the saved tensor.

Keep the DistributedWeight objects as ordinary ctx / LinearBwdArgs references
and prefer them over the saved tensors in backward.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Xiaowei Ren <xren@nvidia.com>
Regression coverage for keeping DistributedWeight objects on the autograd
context: with torch.autograd.graph.saved_tensors_hooks installed, autograd
unpacks a saved leaf as a fresh plain tensor, so gating backward on
is_distributed_weight(saved_weight) silently takes the plain-parameter branch.

Tests, using an in-repo fake DistributedWeight with distinct forward/backward
materialize scales and hook call counters:
  * premise: a saved DistributedWeight comes back as torch.Tensor under hooks;
  * Linear and GroupedLinear (split-quantize path), with and without fused
    weight-gradient accumulation: under identity hooks every DistributedWeight
    hook still fires and outputs / dgrad / wgrad match the unhooked run bitwise.

Without the fix the hooked cases fail in the dgrad GEMM (wrong weight
representation) or with "weight was removed while fuse_wgrad_accumulation=True".

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Xiaowei Ren <xren@nvidia.com>
@xrennvidia
xrennvidia force-pushed the xren/dist-weight-saved-tensor-hooks branch from 45d5cb7 to eea3da3 Compare September 18, 2026 09:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community-contribution PRs from external contributor outside the core maintainers, representing community-driven work.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant