Skip to content

[None][fix] Make graph exit depend on unreturned in-place side effects (staging) - #3

Draft
zheyuf wants to merge 1 commit into
mainfrom
zheyu/fix/multistream-inplace-exit-dep
Draft

zheyuf wants to merge 1 commit into
mainfrom
zheyu/fix/multistream-inplace-exit-dep

Conversation

@zheyuf

@zheyuf zheyuf commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Staging PR for self-review. Generic multi-stream scheduler fix split out of the MiniMax-M3 Eagle3 consolidation (#2) so the Eagle3 PR touches no shared torch.compile path. Cherry-picked from NVIDIA#18066 (343310a); intended to be opened against main on its own once reviewed here. No CI on this fork.

Description

The multi-stream scheduler rebuilds the FX graph from its stream assignment. An in-place op that mutates a graph input without returning a value (Eagle3 captures decoder hidden states into a preallocated buffer with inplace_slice_copy) has no path to the FX output, so the scheduler could emit it after the output node, where it is dead code once the module is recompiled. On the MiniMax-M3 disaggregated context worker (piecewise torch.compile, max_num_streams=3) this dropped the final hidden-state capture and lowered Eagle3 acceptance length from 3.48 to 3.24 on GSM8K.

Make graph exit depend on the last mutation of every in-place target: the mutation is then emitted before output, and when auxiliary streams are live the exit also waits on the mutating stream before a graph-external consumer reads the buffer. No model-specific op, event or configuration gate is needed.

Test Coverage

  • tests/unittest/_torch/compilation/test_auto_multi_stream.py (new): the exit node depends on an unreturned in-place mutation and waits on its stream; every hidden-state capture of a decoder stack (including the last layer's) precedes output and survives recompilation, for 2 and 3 streams. Scheduled via unittest/_torch/compilation in l0_b200 / l0_h100.

PR Checklist

  • PR title follows the [JIRA/NVBUG/None][type] format
  • Commit is signed off (DCO)
  • yapf/isort (legacy file) and ruff (new test) clean
  • CI (/bot run, once opened against main)

The multi-stream scheduler rebuilds the FX graph from its stream assignment.
An in-place op that mutates a graph input without returning a value (Eagle3
captures decoder hidden states into a preallocated buffer with
inplace_slice_copy) has no path to the FX output, so the scheduler could emit
it after the output node, where it is dead code once the module is
recompiled. On the MiniMax-M3 disaggregated context worker (piecewise
torch.compile, max_num_streams 3) this dropped the final hidden-state capture
and lowered Eagle3 acceptance from 3.48 to 3.24 on GSM8K; aggregated serving
with the same compile settings measured 2.98.

Make graph exit depend on the last mutation of every in-place target. The
mutation is then emitted before output, and when auxiliary streams are live
the exit also waits on the mutating stream before a graph-external consumer
reads the buffer. This replaces the Eagle-specific priority edge with a
general dependency and needs no model-specific op, event or configuration
gate.

Restore the scheduler unit test and extend it to assert that every capture
precedes output, including captures of the last decoder layer.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Zheyu Fu <zheyuf@nvidia.com>
(cherry picked from commit 343310a)
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.

1 participant