Skip to content

[PyTorch] Fix deferred initialization in fusible ops - #3327

Open
denera wants to merge 1 commit into
NVIDIA:mainfrom
denera:pytorch/fusible-ops-meta-init-fix
Open

[PyTorch] Fix deferred initialization in fusible ops#3327
denera wants to merge 1 commit into
NVIDIA:mainfrom
denera:pytorch/fusible-ops-meta-init-fix

Conversation

@denera

@denera denera commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Description

Ops replace their params when materializing them on the first fuser forward pass, which invalidated the fuser's cached params and ops.Linear's parameter aliases. Backward then failed with a meta-vs-cuda device mismatch.

  • Re-cache the basic ops params after first materialization
  • Run first forward initialization on the top-level ops, before the cached params are used to pick which ops require backward
  • Sync te.ops.Linear weight/bias aliases with its basic ops
  • Add deferred initialization tests for the affected ops

Fixes #3322

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

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

Ops replace their params when materializing them on the first fuser
forward pass, which invalidated the fuser's cached params and
ops.Linear's parameter aliases. Backward then failed with a
meta-vs-cuda device mismatch.

- Re-cache the basic ops' params after first-forward materialization
- Run first-forward initialization on the top-level ops, before the
  cached params are used to pick which ops require backward
- Sync ops.Linear weight/bias aliases with its basic ops
- Add deferred initialization tests for the affected ops

Fixes NVIDIA#3322

Signed-off-by: Alp Dener <adener@nvidia.com>
@denera denera self-assigned this Aug 7, 2026
@denera
denera requested a review from timmoon10 as a code owner August 7, 2026 15:04
@greptile-apps

greptile-apps Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR fixes deferred initialization for PyTorch fusible operations by initializing top-level operations before backward selection, refreshing cached basic-operation parameters after materialization, and synchronizing Linear parameter aliases. It also adds CUDA forward/backward coverage for deferred initialization across basic, grouped, composite, sequential, and quantized operations.

  • Preserve the original top-level operation list so composite initialization hooks run before fusion planning.
  • Rebuild flattened parameter caches after meta-device parameters materialize.
  • Synchronize Linear.weight and Linear.bias with their underlying basic operations.
  • Test materialization, gradients, device placement, alias identity, and quantized weights.

Confidence Score: 5/5

The PR appears safe to merge, with no concrete blocking or non-blocking defects identified in the changed paths.

First-forward initialization now reaches nested basic operations, synchronizes wrapper aliases, and refreshes the parameter cache before backward eligibility and fusion planning consume it.

Important Files Changed

Filename Overview
transformer_engine/pytorch/ops/fuser.py Defers parameter caching until first-forward initialization and orders recipe reset, top-level materialization, cache refresh, and fusion planning consistently.
transformer_engine/pytorch/ops/linear.py Re-registers Linear parameter aliases after its underlying basic operations replace meta-device parameters.
tests/pytorch/test_fusible_ops.py Adds deferred-initialization forward/backward tests covering device placement, gradients, aliases, grouped parameters, composition, and quantized weights.

Sequence Diagram

sequenceDiagram
  participant User
  participant Fuser as OperationFuser
  participant Basic as Basic operations
  participant Top as Top-level operations
  participant Autograd
  User->>Fuser: First forward
  Fuser->>Basic: reset_recipe_state(recipe)
  Fuser->>Top: pre_first_fuser_forward()
  Top->>Basic: materialize meta parameters
  Top->>Top: synchronize parameter aliases
  Fuser->>Basic: cache materialized parameters
  Fuser->>Fuser: select and build forward/backward fusions
  Fuser->>Autograd: execute with refreshed parameters
  Autograd-->>User: outputs and parameter gradients
Loading

Reviews (1): Last reviewed commit: "[PyTorch] Fix deferred initialization in..." | Re-trigger Greptile

@denera

denera commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator Author

/te-ci pytorch

@vthumbe1503 vthumbe1503 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, have some question and a minor suggestion for adding grouped_linear test case as well for quantized_model_int case

# Construct operation on meta device
recipe = make_recipe(quantization)
with te.quantized_model_init(enabled=quantized_weight, recipe=recipe):
op = te_ops.Linear(size, size, bias=True, device="meta", dtype=dtype)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we extend this test for GroupedLinear as well?

Comment on lines +448 to +452
op.reset_recipe_state(recipe=recipe)
for op in self._ops:
op.pre_first_fuser_forward()

# Cache params now that ops have initialized them

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If somebody calls register_parameter on the ops in a later iteration, this means it would not get cached in fuser's parameter list

I know it is a weird use-case, and maybe nobody does this. But was this always intended, @timmoon10 ?

if op_type.startswith("grouped_linear"):
in_shape = (size * num_groups, size)
extra_inputs.append(torch.tensor([size] * num_groups, dtype=torch.int, device=device))
x = torch.randn(in_shape, dtype=dtype, device=device, requires_grad=True)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should test both requires_grad = True and False

Comment on lines +775 to +784
# Check that params have been materialized
assert op.weight is op.basic_ops[op._linear_idx].weight
assert op.bias is op.basic_ops[op._bias_idx].bias
if quantized_weight:
assert isinstance(op.weight, QuantizedTensor)
for name, param in op.named_parameters():
assert param.device.type == device, f"{name} was not materialized on {device}"
assert param.grad is not None, f"{name} did not get a grad"
assert param.grad.device.type == device, f"{name} got a grad on {param.grad.device}"
assert x.grad is not None and x.grad.device.type == device

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to that there should be some testing that the resulting output/gradients actually match the op that did not go through this materialization step.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Deferred init issue in te.pytorch.ops

3 participants