Skip to content

fix(lowering): keep dynamic dims through complex lowering - #4896

Merged
lanluo-nvidia merged 3 commits into
mainfrom
narendasan/complex-dynamic-dims
Oct 29, 2026
Merged

lanluo-nvidia merged 3 commits into
mainfrom
narendasan/complex-dynamic-dims

Conversation

@narendasan

@narendasan narendasan commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

PyTorch's decompose_complex_in_graph retraces with make_fx in real mode. Tensor factories such as arange(seq) can then specialize the exported program's symbolic dimensions, leaving complex rotary models unable to accept other input shapes.

Dynamic graphs now use the upstream complex dispatch and mutation check through a small wrapper that selects tracing_mode="symbolic". Static graphs continue to use the upstream entry point. Unsupported-op and older-PyTorch fallbacks remain as before.

This replaces the original blanket fallback to the legacy rewriter, which regressed complex prod, complex scalar arithmetic, complex construction, and refit's reference input layout.

Validation

  • All 20 adapter tests passed on CPU with PyTorch 2.15, loading the workspace adapter and decomposition table against the installed Torch-TensorRT package.
  • Eight new regression cases cover the four reported operations with and without symbolic arange, preserve complex input/output metadata, and check two batch sizes. They fail against the original blanket fallback and pass with symbolic tracing.
  • The existing rotary arange(seq) test passes at a different sequence length.
  • Extended the complex-buffer refit test to dynamic batches, asserted successful verify_output=True, and checked alternate batch sizes after refitting. GPU execution remains for CI because CUDA is unavailable locally.
  • All commit hooks passed, including mypy, Ruff, isort, Black, and typos.

complex_decomposition_adapter hands the graph to upstream's
decompose_complex_in_graph, which retraces it with make_fx in real mode.
There an op that builds a tensor of symbolic size, such as arange(seq) for
rotary positions, needs a concrete value, so the retrace guards the symbol to
its traced value in the exported program's ShapeEnv. Every engine built
afterwards is static: Llama 4 and DeepSeek-V2 compiled with a dynamic batch
and sequence refuse any other shape at runtime.

Graphs with symbolic input dims now take the legacy complex_graph_detection
pass, which keeps them symbolic. The check runs before the retrace, since the
guard it adds outlives the retrace.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@meta-cla meta-cla Bot added the cla signed label Oct 21, 2026
@github-actions github-actions Bot added component: tests Issues re: Tests component: lowering Issues re: The lowering / preprocessing passes component: core Issues re: The core compiler component: api [Python] Issues re: Python API component: dynamo Issues relating to the `torch.compile` or `torch._dynamo.export` paths labels Oct 21, 2026
@github-actions
github-actions Bot requested a review from zewenli98 October 21, 2026 05:09

@shoumikhin shoumikhin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The fix works for the rotary case, and the new test fails without it and passes with it. But it makes some dynamic models that are correct today return wrong numbers, see inline. Tested on A100.

)

flat_args = _fake_flat_args(gm)
if any(free_symbols(arg) for arg in flat_args):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This sends every complex graph with a dynamic dim to the legacy rewriter, and the legacy rewriter gets some ops wrong. So some dynamic models that are correct today now compile without error and return wrong numbers. With a dynamic batch, main vs this PR:

  • torch.prod(z, dim=1): correct before, wrong after
  • z + (1+2j) and z * (2-1j): correct before, wrong after
  • torch.complex(z.real * 2, z.imag): correct before, wrong output shape after

These ops are also wrong on the legacy path with static shapes, so the bugs are in the legacy rewriter. For example, its prod.dim_int rewrite multiplies the real parts and the imaginary parts separately. Refit with verify_output=True also fails now for a model with a dynamic complex input.

Could the fallback be limited to graphs the retrace really specializes? Or could those legacy ops be fixed first? A dynamic-shape test with complex prod would catch this kind of regression.

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.

Agreed—the blanket dynamic-shape fallback regressed operations that upstream already handles correctly. Fixed in bc118cf. Dynamic graphs now use upstream's ComplexTensor dispatch with make_fx(tracing_mode="symbolic"), preserving arange(seq) and other symbolic factories without routing supported ops through the legacy rewriter. The small wrapper retains upstream's mutation check; static graphs keep the upstream entry point.

Added regression coverage for all four examples (prod, complex scalar add/mul, and torch.complex), with and without a symbolic arange in the same graph, at two batch sizes. The tests also check that complex inputs and output metadata remain intact for refit's reference module. All eight cases fail against the original PR fallback and pass with this change; all 20 adapter tests pass locally on PyTorch 2.15 using the workspace adapter and decomposition table.

Also extended the complex-buffer refit test to dynamic batch sizes, asserted that verify_output=True reports success, and checked other batch sizes after refitting. That GPU test is added for CI; CUDA is unavailable locally, so I have not claimed an end-to-end refit pass. All commit hooks passed.

@zewenli98 zewenli98 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.

Maybe @apbose can take a review

@lanluo-nvidia lanluo-nvidia added this to the v2.15.0 milestone Oct 29, 2026
@github-actions
github-actions Bot requested a review from zewenli98 October 29, 2026 19:10
@apbose

apbose commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

LGTM now with the new commit. As @shoumikhin had pointed the change earlier regressed complex prod, scalar add/mul and torch.complex. But then yeah we should have a followup PR to correct those. Also could also file an upstream pytorch change maybe to support this symbolic tracing mode.

@lanluo-nvidia
lanluo-nvidia merged commit af4ca28 into main Oct 29, 2026
125 of 141 checks passed
lanluo-nvidia added a commit that referenced this pull request Oct 29, 2026
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Lan Luo <lanl@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci: full cla signed component: api [Python] Issues re: Python API component: core Issues re: The core compiler component: dynamo Issues relating to the `torch.compile` or `torch._dynamo.export` paths component: lowering Issues re: The lowering / preprocessing passes component: tests Issues re: Tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants