Skip to content

fix(dist): keep profiler record-function ops out of SAC replay accounting - #3133

Merged
HuiyingLi merged 4 commits into
mainfrom
huiyingl/fix/sac-ignore-profiler-ops
Jul 24, 2026
Merged

fix(dist): keep profiler record-function ops out of SAC replay accounting#3133
HuiyingLi merged 4 commits into
mainfrom
huiyingl/fix/sac-ignore-profiler-ops

Conversation

@HuiyingLi

@HuiyingLi HuiyingLi commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

What

Adds torch.ops.profiler._record_function_{enter,enter_new,exit} (all overloads) to torch.utils.checkpoint.SAC_IGNORED_OPS, applied from both selective-AC context factories (activation_checkpointing.make_selective_checkpoint_context_fn and the MoE parallelizer.apply_ac SAC path).

Why

torch 2.13 (pytorch:26.06-py3 base, 2.13.0a0+8145d630e8) runs FSDP2 pre/post-forward hooks under torch.autograd.profiler.record_function, which emits dispatchable torch.ops.profiler ops. With an FSDP module boundary inside a SAC region (MoE experts fully_shard-ed separately inside a checkpointed decoder block), the hooks fire a different number of times during backward recompute than during forward. SAC replays the forward op stream by per-op invocation index, so the extra profiler op desyncs the replay:

RuntimeError: profiler._record_function_enter_new.default invocation index 3 encountered during backward but not found in storage. This can happen if the operations in the checkpointed region are nondeterministic ...

Hit by qwen3_6_35b_medpix_ep8cp2_4k (both on main and on PR branches — pre-existing, torch-2.13-only) in nemo-ci runs on the 26.06 base: identical failure on merge-base 5008ea6 and on the #2937 branch (jobs 367239212 / 367239239). The same recipe passes on the pytorch 26.04 base (torch 2.12), and upstream SAC_IGNORED_OPS still doesn't cover profiler ops on pytorch main.

Range ops carry no tensors SAC could cache or restore — ignoring them only removes them from replay accounting; they still execute.

Testing

  • CPU regression test: a checkpointed function enters a record_function range only during the backward-time recompute; without the fix SAC raises the storage error, with it backward succeeds.
  • Local 8xH100 torch 2.13 SAC/profiler repro: without the fix it reproduces profiler._record_function_enter_new.default ... not found in storage; with PR fix(dist): keep profiler record-function ops out of SAC replay accounting #3133 source overlaid, all ranks pass.
  • nemo-ci validation on the 26.06 base (torch 2.13), eos: qwen3_6_35b_medpix_ep8cp2_4k passed with this fix (root pipeline 58616157, job 367298896; details in PR comment).
  • Same-image nemo-ci validation for the original failing config nemotron_super_v3_te_deepep passed with this fix overlaid at runtime:

🤖 Generated with Claude Code

…ting

torch 2.13's FSDP2 runs its pre/post-forward hooks under
torch.autograd.profiler.record_function, which emits dispatchable
torch.ops.profiler ops. When an FSDP module boundary sits inside a
selective-activation-checkpointed region (MoE experts sharded separately
inside a checkpointed decoder block), the hooks fire a different number
of times during the backward recompute than during the forward. SAC
replays the forward op stream by per-op invocation index, so the extra
profiler op shifts the stream and training fails with:

  RuntimeError: profiler._record_function_enter_new.default invocation
  index 3 encountered during backward but not found in storage.

Seen on qwen3_6_35b_medpix_ep8cp2_4k with the pytorch:26.06-py3 base
(torch 2.13.0a0+8145d630e8); upstream SAC_IGNORED_OPS does not cover
profiler ops as of pytorch/pytorch@main. Range ops carry no tensors SAC
could cache, so adding them to SAC_IGNORED_OPS only removes them from
replay accounting - they still execute.

Applied from both SAC context factories (activation_checkpointing and
the MoE parallelizer). CPU regression test enters a record_function
range only during the recompute pass and asserts backward succeeds.

Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
@copy-pr-bot

copy-pr-bot Bot commented Jul 19, 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.

@HuiyingLi

Copy link
Copy Markdown
Contributor Author

nemo-ci validation on the pytorch:26.06-py3 base (torch 2.13.0a0+8145d630e8), 20 steps, eos:

qwen3_6_35b_medpix_ep8cp2_4k — PASSED with this fix

Known remaining torch-2.13 issue (separate from this PR): deepseek_v4_flash_cp_tulu3 on the same base now gets past stage-shape init (main's _set_stage_metas compat from a5b9283 works) and past the profiler ops (this fix), but then hits a deeper SAC replay divergence — aten.add_.Tensor encountered during backward but not found in storage (job 367298563, pipeline 58616158). That is a genuine forward-vs-recompute op-stream divergence under FSDP2 + SAC + pp4/cp8 on torch 2.13, not a profiler-range artifact; it does not reproduce on the pytorch 26.04 base (torch 2.12), where the same recipe passes 20/20 steps.

🤖 Generated with Claude Code

@HuiyingLi
HuiyingLi marked this pull request as ready for review July 22, 2026 07:22
@HuiyingLi
HuiyingLi requested a review from a team as a code owner July 22, 2026 07:22
@HuiyingLi

Copy link
Copy Markdown
Contributor Author

/claude review

@claude

claude Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

LGTM

@HuiyingLi

Copy link
Copy Markdown
Contributor Author

/ok to test a87b25d

still execute). No-op on torch builds without ``SAC_IGNORED_OPS`` or the
profiler op namespace.
"""
sac_ignored = getattr(torch.utils.checkpoint, "SAC_IGNORED_OPS", None)

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.

@HuiyingLi would it make sense to gate on pyt version? 🙇

@akoumpa

akoumpa commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

/ok to test 0d981f4

Only add profiler record-function ops to SAC_IGNORED_OPS on PyTorch 2.13+
builds, including NVIDIA alpha builds that report 2.13.0a0. This keeps older
unaffected torch builds on the default SAC ignored-op set.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
@HuiyingLi

Copy link
Copy Markdown
Contributor Author

/ok to test b546d90

@HuiyingLi
HuiyingLi merged commit dfd1401 into main Jul 24, 2026
83 checks passed
@HuiyingLi
HuiyingLi deleted the huiyingl/fix/sac-ignore-profiler-ops branch July 24, 2026 17:45
HuiyingLi added a commit that referenced this pull request Jul 26, 2026
…ting (#3133)

* fix(dist): keep profiler record-function ops out of SAC replay accounting

torch 2.13's FSDP2 runs its pre/post-forward hooks under
torch.autograd.profiler.record_function, which emits dispatchable
torch.ops.profiler ops. When an FSDP module boundary sits inside a
selective-activation-checkpointed region (MoE experts sharded separately
inside a checkpointed decoder block), the hooks fire a different number
of times during the backward recompute than during the forward. SAC
replays the forward op stream by per-op invocation index, so the extra
profiler op shifts the stream and training fails with:

  RuntimeError: profiler._record_function_enter_new.default invocation
  index 3 encountered during backward but not found in storage.

Seen on qwen3_6_35b_medpix_ep8cp2_4k with the pytorch:26.06-py3 base
(torch 2.13.0a0+8145d630e8); upstream SAC_IGNORED_OPS does not cover
profiler ops as of pytorch/pytorch@main. Range ops carry no tensors SAC
could cache, so adding them to SAC_IGNORED_OPS only removes them from
replay accounting - they still execute.

Applied from both SAC context factories (activation_checkpointing and
the MoE parallelizer). CPU regression test enters a record_function
range only during the recompute pass and asserts backward succeeds.

Signed-off-by: HuiyingLi <willwin.lee@gmail.com>

* fix(dist): gate profiler SAC ignore on torch 2.13

Only add profiler record-function ops to SAC_IGNORED_OPS on PyTorch 2.13+
builds, including NVIDIA alpha builds that report 2.13.0a0. This keeps older
unaffected torch builds on the default SAC ignored-op set.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: HuiyingLi <willwin.lee@gmail.com>

---------

Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Co-authored-by: Alexandros Koumparoulis <153118171+akoumpa@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

2 participants