Skip to content

ShardTensor: fixes for torch.compile with domain parallelism (#1986) - #2210

Draft
coreyjadams wants to merge 8 commits into
mainfrom
dp-06-compile-1986
Draft

coreyjadams wants to merge 8 commits into
mainfrom
dp-06-compile-1986

Conversation

@coreyjadams

Copy link
Copy Markdown
Collaborator

PhysicsNeMo Pull Request

Description

Fixes the torch.compile + ShardTensor failures from #1986 that remained after
the domain-parallel stack (#1979 to #1983). Each fix has a test that fails without it.

  • na1d/na2d/na3d under compile. Dynamo treats ShardTensor as a plain
    tensor and never calls its __torch_function__, so the wrapper's
    has_torch_function check was folded to False and a compiled na2d called
    the raw kernel on the ShardTensor, skipping the halo exchange: wrong results,
    or rank-divergent collectives. With a tensor-subclass operand, na1d/2d/3d
    now call torch.library ops physicsnemo::na{1,2,3}d, and ShardTensor
    registers its halo-exchange handler on them with
    register_named_function_handler. That handler runs in eager and under AOT,
    above autograd, so gradients flow through the halo exchange as in eager.
    Plain tensors still call NATTEN directly. On the subclass path only
    is_causal, scale and backend are passed through; other NATTEN options
    raise. NATTEN's own ops can't be hooked instead: its Hopper/Blackwell
    backends permute tokens into tiles before calling them. The test uses a
    pure-torch reference kernel, so it runs without NATTEN.
  • select / select_backward with a negative dim. The handlers compared
    shard dims against dim as written; dim=-1 (stack's backward, e.g. RoPE
    rotate-half under compile) relabeled Shard(2) as Shard(1) on the gradient.
  • Symbolic shapes (🐛[BUG]: torch.compile + ShardTensor failures with regional model recipe #1986 item 6). With dynamic=True, the spec holds
    SymInts, which are unhashable: the spec hash and the alignment check both
    raised. The hash falls back to (mesh, placements); the alignment check
    skips symbolic layouts. Because symbolic specs now share a hash, specs from
    different compiles meet in the spec cache; __eq__ compares their SymInts
    by identity only, instead of raising "SymInt ... not tracked" (seen on the
    1-GPU UNet force_sharding compile).
  • Mixed DTensor and ShardTensor operands (🐛[BUG]: torch.compile + ShardTensor failures with regional model recipe #1986 item 3). Under tracing, a
    plain DTensor operand (e.g. a Replicate parameter such as the DiT mask
    token) took the op and rejected the ShardTensor. Such ops now use the DTensor
    fallback, as in eager.
  • Plain-parameter gradients under compile. A plain parameter that meets a
    ShardTensor got an unreduced ShardTensor(Partial) gradient under compile,
    which FSDP2 rejects. Under tracing, ops with a grad-requiring plain operand
    now take the differentiable promotion, so the gradient is reduced as in
    eager. Limited to exact plain types (Tensor, Parameter, and their
    FakeTensor / FunctionalTensor stand-ins) with grad mode on, so other
    tensor subclasses keep their own dispatch.

Not addressed here:

Validated on 4 GPUs: test/domain_parallel (natten, natten compile, DiT,
spec cache, compile) green; the regional weather diffusion recipe trains
compiled with domain parallelism on 1, 2 and 4 GPUs (next PR).

Checklist

Dependencies

None.

@copy-pr-bot

copy-pr-bot Bot commented Oct 30, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions

Copy link
Copy Markdown
Contributor

CODEOWNERS review map

Current for commit 9626e5baf276. An approval covers every file listed for that owner; one owner is sufficient for shared files.

⏳ @coreyjadams — 9 file(s)
  • physicsnemo/domain_parallel/_shard_tensor_spec.py
  • physicsnemo/domain_parallel/shard_tensor.py
  • physicsnemo/domain_parallel/shard_utils/index_ops.py
  • physicsnemo/domain_parallel/shard_utils/natten_patches.py
  • test/domain_parallel/ops/test_natten_compile.py
  • test/domain_parallel/ops/test_select.py
  • test/domain_parallel/test_compile.py
  • test/domain_parallel/test_spec_and_plan_cache.py
  • test/domain_parallel/test_tracing_promotion.py
⏳ @negin513 — 9 file(s)
  • physicsnemo/domain_parallel/_shard_tensor_spec.py
  • physicsnemo/domain_parallel/shard_tensor.py
  • physicsnemo/domain_parallel/shard_utils/index_ops.py
  • physicsnemo/domain_parallel/shard_utils/natten_patches.py
  • test/domain_parallel/ops/test_natten_compile.py
  • test/domain_parallel/ops/test_select.py
  • test/domain_parallel/test_compile.py
  • test/domain_parallel/test_spec_and_plan_cache.py
  • test/domain_parallel/test_tracing_promotion.py
⏳ @peterdsharpe — 9 file(s)
  • physicsnemo/domain_parallel/_shard_tensor_spec.py
  • physicsnemo/domain_parallel/shard_tensor.py
  • physicsnemo/domain_parallel/shard_utils/index_ops.py
  • physicsnemo/domain_parallel/shard_utils/natten_patches.py
  • test/domain_parallel/ops/test_natten_compile.py
  • test/domain_parallel/ops/test_select.py
  • test/domain_parallel/test_compile.py
  • test/domain_parallel/test_spec_and_plan_cache.py
  • test/domain_parallel/test_tracing_promotion.py
⏳ @pzharrington — 1 file(s)
  • physicsnemo/nn/functional/natten.py

No CODEOWNER

  • CHANGELOG.md
  • test/nn/functional/test_natten.py

Comment /codeowners-info to refresh.

@coreyjadams
coreyjadams added this pull request to stack #2212 October 30, 2026 21:45
Dynamo folds has_torch_function to False for traceable wrapper subclasses,
so a compiled na2d called the raw kernel on the ShardTensor and skipped the
halo exchange (wrong results, or rank-divergent collectives). Under compile,
route subclass calls through an allow_in_graph helper: Dynamo records one
graph node and fake propagation runs the handler, as for torch ops.

Test uses a pure-torch reference kernel, so it runs without NATTEN.
The dispatch handlers compared shard dims against dim as written: dim=-1
(stack's backward, e.g. RoPE rotate-half under compile) relabeled Shard(2)
as Shard(1) on the gradient, and a negative dim on the sharded axis escaped
the guard.
With dynamic shapes, tensor_meta holds SymInts, which are unhashable: the
spec hash (DTensor sharding propagation) and validate_aligned_sharding's
layout key both raised. The hash falls back to (mesh, placements); the
alignment check skips symbolic layouts.
…compile

Under tracing, unpatched ops went straight to dispatch; a plain DTensor
operand (e.g. a Replicate parameter like the DiT mask token) then took the
op and rejected the ShardTensor ('got mixed torch.Tensor and DTensor').
Such ops now use the DTensor fallback, as in eager.
Under tracing, ops with a grad-requiring plain operand (exact Tensor,
Parameter, FakeTensor or FunctionalTensor; grad mode on) take the DTensor
fallback, whose differentiable promotion reduces the Partial grad to a
plain tensor as in eager. Other tensor subclasses keep their dispatch.
Symbolic specs hash by (mesh, placements) only, so specs from different
compiles collide in the spec cache. Comparing their SymInts raised
'SymInt ... not tracked' (1-GPU UNet force_sharding compile). Compare
ints by value and SymInts by identity; anything else is a cache miss.
Dynamo treats ShardTensor as a plain tensor and never calls its
__torch_function__, so a Python-level has_torch_function check (or
allow_in_graph) can't reach the ShardTensor handler cleanly. na1d/2d/3d
now call torch.library custom ops when an operand is a tensor subclass;
ShardTensor registers the halo-exchange handler on them with
register_named_function_handler, which runs in eager and under AOT.
Plain tensors still call NATTEN directly.
@coreyjadams coreyjadams added the ci:multi-gpu Run this PR on multiGPU ci label Oct 30, 2026

This branch has not been deployed

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

Labels

ci:multi-gpu Run this PR on multiGPU ci

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant