[graph_trainer] Add CooR precompile support for aot_fx_trace compile mode#2975
Merged
Conversation
bobrenjc93
added a commit
that referenced
this pull request
Apr 15, 2026
…mode Introduce aot_fx_trace as an alternate precompilation path alongside the existing AOT joint graph export. aot_fx_trace uses make_fx to trace the full fwd+loss+bwd step as a single FX graph, then serializes the GraphModule for loading on all ranks during training. Because cudagraphs is a default pass, we also include cudagraph composability related changes in this PR to get to bitwise equivalence between aot_fx_trace with and without precompile. Changes: - precompile_main.py: Refactor into _common_setup() + _precompile_aot() + _precompile_aot_fx_trace(), route by --compile.mode. Use Python float for global_valid_tokens (matching dist_sum's return type) so make_fx bakes it as a graph constant, identical to the runtime path. - precompile.py: PrecompiledFxTraceArtifact dataclass, save/load fns. Uses GraphPickler (not plain pickle) to preserve SymInt expressions (_runtime_compute_coordinate_on_dim) through serialization — plain pickle evaluates SymInts to concrete trace-time values, baking in rank-specific embedding vocab offsets. - compile.py: Mode-aware validation (aot_fx_trace doesn't need serializable passes), logging for precompile load vs runtime trace - trainer.py: _load_precompiled_fx_trace(), branching in _make_fx_forward_backward_step() - make_fx_tracer.py: Use set_multithreading_enabled(False) so backward tracing runs on the calling thread, keeping the compile_on_one_rank ContextVar visible - cudagraph.py: Defer _input_indices_to_copy when example_inputs is empty (precompile load path), accept opaque values (DeviceMesh) in input validation, skip non-tensors in static address checks. Squashed the separate cudagraph CooR PR into this one because cudagraph activates automatically for aot_fx_trace graphs (all inputs are desugared plain tensors + opaques, no HOPs), so bitwise equivalence testing required both fixes together. - passes.py: Guard cudagraph_pass against non-GraphModule inputs Numerics (llama3 debugmodel, 8xH100, FSDP4+TP2, 50 steps, deterministic): - 50/50 steps BITWISE IDENTICAL between precompile and non-precompile - Loss/grad_norm/MFU: https://pxl.cl/9pNvp - Cudagraph profile: https://pxl.cl/9pNB0 ghstack-source-id: 5cfa431 Pull-Request: #2975
…mode
Introduce aot_fx_trace as an alternate precompilation path alongside
the existing AOT joint graph export. aot_fx_trace uses make_fx to
trace the full fwd+loss+bwd step as a single FX graph, then serializes
the GraphModule for loading on all ranks during training.
Key differences from AOT precompile:
- Traces fwd+loss+bwd together (no AOTAutograd partitioning)
- Serializes the FX graph, not compiled Triton kernels
- Inductor compilation happens at load time on each rank
- No pipeline parallel support (no graph partitioning)
Changes:
- precompile_main.py: Refactor into _common_setup() + _precompile_aot()
+ _precompile_aot_fx_trace(), route by --compile.mode. Use Python
float for global_valid_tokens (matching dist_sum's return type) so
make_fx bakes it as a graph constant, identical to the runtime path.
- precompile.py: PrecompiledFxTraceArtifact dataclass, save/load fns.
Uses GraphPickler (not plain pickle) to preserve SymInt expressions
(_runtime_compute_coordinate_on_dim) through serialization — plain
pickle evaluates SymInts to concrete trace-time values, baking in
rank-specific embedding vocab offsets.
- compile.py: Mode-aware validation (aot_fx_trace doesn't need
serializable passes), logging for precompile load vs runtime trace
- trainer.py: _load_precompiled_fx_trace(), branching in
_make_fx_forward_backward_step()
- make_fx_tracer.py: Use set_multithreading_enabled(False) so backward
tracing runs on the calling thread, keeping the compile_on_one_rank
ContextVar visible
- cudagraph.py: Defer _input_indices_to_copy when example_inputs is
empty (precompile load path), accept opaque values (DeviceMesh) in
input validation, skip non-tensors in static address checks.
Squashed the separate cudagraph CooR PR into this one because
cudagraph activates automatically for aot_fx_trace graphs (all
inputs are desugared plain tensors + opaques, no HOPs), so bitwise
equivalence testing required both fixes together.
- passes.py: Guard cudagraph_pass against non-GraphModule inputs
Test plan:
- pytest torchtitan/experiments/graph_trainer/tests/test_bitwise_deterministic.py -x
— 6 passed, 4 skipped (Llama3, DSv3 × {eager self-deterministic,
eager vs aot_fx_trace, precompile vs trace})
- pytest torchtitan/experiments/graph_trainer/tests/test_precompile.py -x — all pass
- pytest torchtitan/experiments/graph_trainer/tests/test_trace_module.py -x — all pass
- 8-GPU integration tests via CI (ciflow/8gpu)
ghstack-source-id: 3691eb1
Pull-Request: #2975
0815019 to
ba1cf36
Compare
2f733f7 to
98ec7b4
Compare
[ghstack-poisoned]
bobrenjc93
added a commit
that referenced
this pull request
Apr 15, 2026
…mode
Introduce aot_fx_trace as an alternate precompilation path alongside
the existing AOT joint graph export. aot_fx_trace uses make_fx to
trace the full fwd+loss+bwd step as a single FX graph, then serializes
the GraphModule for loading on all ranks during training.
Key differences from AOT precompile:
- Traces fwd+loss+bwd together (no AOTAutograd partitioning)
- Serializes the FX graph, not compiled Triton kernels
- Inductor compilation happens at load time on each rank
- No pipeline parallel support (no graph partitioning)
Changes:
- precompile_main.py: Refactor into _common_setup() + _precompile_aot()
+ _precompile_aot_fx_trace(), route by --compile.mode. Use Python
float for global_valid_tokens (matching dist_sum's return type) so
make_fx bakes it as a graph constant, identical to the runtime path.
- precompile.py: PrecompiledFxTraceArtifact dataclass, save/load fns.
Uses GraphPickler (not plain pickle) to preserve SymInt expressions
(_runtime_compute_coordinate_on_dim) through serialization — plain
pickle evaluates SymInts to concrete trace-time values, baking in
rank-specific embedding vocab offsets.
- compile.py: Mode-aware validation (aot_fx_trace doesn't need
serializable passes), logging for precompile load vs runtime trace
- trainer.py: _load_precompiled_fx_trace(), branching in
_make_fx_forward_backward_step()
- make_fx_tracer.py: Use set_multithreading_enabled(False) so backward
tracing runs on the calling thread, keeping the compile_on_one_rank
ContextVar visible
- cudagraph.py: Defer _input_indices_to_copy when example_inputs is
empty (precompile load path), accept opaque values (DeviceMesh) in
input validation, skip non-tensors in static address checks.
Squashed the separate cudagraph CooR PR into this one because
cudagraph activates automatically for aot_fx_trace graphs (all
inputs are desugared plain tensors + opaques, no HOPs), so bitwise
equivalence testing required both fixes together.
- passes.py: Guard cudagraph_pass against non-GraphModule inputs
Test plan:
- pytest torchtitan/experiments/graph_trainer/tests/test_bitwise_deterministic.py -x
— 6 passed, 4 skipped (Llama3, DSv3 × {eager self-deterministic,
eager vs aot_fx_trace, precompile vs trace})
- pytest torchtitan/experiments/graph_trainer/tests/test_precompile.py -x — all pass
- pytest torchtitan/experiments/graph_trainer/tests/test_trace_module.py -x — all pass
- 8-GPU integration tests via CI (ciflow/8gpu)
ghstack-source-id: 82fc5d8
Pull-Request: #2975
[ghstack-poisoned]
bobrenjc93
added a commit
that referenced
this pull request
Apr 15, 2026
…mode
Introduce aot_fx_trace as an alternate precompilation path alongside
the existing AOT joint graph export. aot_fx_trace uses make_fx to
trace the full fwd+loss+bwd step as a single FX graph, then serializes
the GraphModule for loading on all ranks during training.
Key differences from AOT precompile:
- Traces fwd+loss+bwd together (no AOTAutograd partitioning)
- Serializes the FX graph, not compiled Triton kernels
- Inductor compilation happens at load time on each rank
- No pipeline parallel support (no graph partitioning)
Changes:
- precompile_main.py: Refactor into _common_setup() + _precompile_aot()
+ _precompile_aot_fx_trace(), route by --compile.mode. Use Python
float for global_valid_tokens (matching dist_sum's return type) so
make_fx bakes it as a graph constant, identical to the runtime path.
- precompile.py: PrecompiledFxTraceArtifact dataclass, save/load fns.
Uses GraphPickler (not plain pickle) to preserve SymInt expressions
(_runtime_compute_coordinate_on_dim) through serialization — plain
pickle evaluates SymInts to concrete trace-time values, baking in
rank-specific embedding vocab offsets.
- compile.py: Mode-aware validation (aot_fx_trace doesn't need
serializable passes), logging for precompile load vs runtime trace
- trainer.py: _load_precompiled_fx_trace(), branching in
_make_fx_forward_backward_step()
- make_fx_tracer.py: Use set_multithreading_enabled(False) so backward
tracing runs on the calling thread, keeping the compile_on_one_rank
ContextVar visible
- cudagraph.py: Defer _input_indices_to_copy when example_inputs is
empty (precompile load path), accept opaque values (DeviceMesh) in
input validation, skip non-tensors in static address checks.
Squashed the separate cudagraph CooR PR into this one because
cudagraph activates automatically for aot_fx_trace graphs (all
inputs are desugared plain tensors + opaques, no HOPs), so bitwise
equivalence testing required both fixes together.
- passes.py: Guard cudagraph_pass against non-GraphModule inputs
Test plan:
- pytest torchtitan/experiments/graph_trainer/tests/test_bitwise_deterministic.py -x
— 6 passed, 4 skipped (Llama3, DSv3 × {eager self-deterministic,
eager vs aot_fx_trace, precompile vs trace})
- pytest torchtitan/experiments/graph_trainer/tests/test_precompile.py -x — all pass
- pytest torchtitan/experiments/graph_trainer/tests/test_trace_module.py -x — all pass
- 8-GPU integration tests via CI (ciflow/8gpu)
ghstack-source-id: 44abd37
Pull-Request: #2975
xmfan
reviewed
Apr 16, 2026
xmfan
reviewed
Apr 16, 2026
xmfan
reviewed
Apr 16, 2026
xmfan
reviewed
Apr 16, 2026
bobrenjc93
added a commit
that referenced
this pull request
Apr 16, 2026
…mode
Introduce aot_fx_trace as an alternate precompilation path alongside
the existing AOT joint graph export. aot_fx_trace uses make_fx to
trace the full fwd+loss+bwd step as a single FX graph, then serializes
the GraphModule for loading on all ranks during training.
Key differences from AOT precompile:
- Traces fwd+loss+bwd together (no AOTAutograd partitioning)
- Serializes the FX graph, not compiled Triton kernels
- Inductor compilation happens at load time on each rank
- No pipeline parallel support (no graph partitioning)
Changes:
- precompile_main.py: Refactor into _common_setup() + _precompile_aot()
+ _precompile_aot_fx_trace(), route by --compile.mode. Use Python
float for global_valid_tokens (matching dist_sum's return type) so
make_fx bakes it as a graph constant, identical to the runtime path.
- precompile.py: PrecompiledFxTraceArtifact dataclass, save/load fns.
Uses GraphPickler (not plain pickle) to preserve SymInt expressions
(_runtime_compute_coordinate_on_dim) through serialization — plain
pickle evaluates SymInts to concrete trace-time values, baking in
rank-specific embedding vocab offsets.
- compile.py: Mode-aware validation (aot_fx_trace doesn't need
serializable passes), logging for precompile load vs runtime trace
- trainer.py: _load_precompiled_fx_trace(), branching in
_make_fx_forward_backward_step()
- make_fx_tracer.py: Use set_multithreading_enabled(False) so backward
tracing runs on the calling thread, keeping the compile_on_one_rank
ContextVar visible
- cudagraph.py: Defer _input_indices_to_copy when example_inputs is
empty (precompile load path), accept opaque values (DeviceMesh) in
input validation, skip non-tensors in static address checks.
Squashed the separate cudagraph CooR PR into this one because
cudagraph activates automatically for aot_fx_trace graphs (all
inputs are desugared plain tensors + opaques, no HOPs), so bitwise
equivalence testing required both fixes together.
- passes.py: Guard cudagraph_pass against non-GraphModule inputs
Test plan:
- pytest torchtitan/experiments/graph_trainer/tests/test_bitwise_deterministic.py -x
— 6 passed, 4 skipped (Llama3, DSv3 × {eager self-deterministic,
eager vs aot_fx_trace, precompile vs trace})
- pytest torchtitan/experiments/graph_trainer/tests/test_precompile.py -x — all pass
- pytest torchtitan/experiments/graph_trainer/tests/test_trace_module.py -x — all pass
- 8-GPU integration tests via CI (ciflow/8gpu)
ghstack-source-id: 23462f9
Pull-Request: #2975
bobrenjc93
added a commit
that referenced
this pull request
Apr 16, 2026
…mode
Introduce aot_fx_trace as an alternate precompilation path alongside
the existing AOT joint graph export. aot_fx_trace uses make_fx to
trace the full fwd+loss+bwd step as a single FX graph, then serializes
the GraphModule for loading on all ranks during training.
Key differences from AOT precompile:
- Traces fwd+loss+bwd together (no AOTAutograd partitioning)
- Serializes the FX graph, not compiled Triton kernels
- Inductor compilation happens at load time on each rank
- No pipeline parallel support (no graph partitioning)
Changes:
- precompile_main.py: Refactor into _common_setup() + _precompile_aot()
+ _precompile_aot_fx_trace(), route by --compile.mode. Use Python
float for global_valid_tokens (matching dist_sum's return type) so
make_fx bakes it as a graph constant, identical to the runtime path.
- precompile.py: PrecompiledFxTraceArtifact dataclass, save/load fns.
Uses GraphPickler (not plain pickle) to preserve SymInt expressions
(_runtime_compute_coordinate_on_dim) through serialization — plain
pickle evaluates SymInts to concrete trace-time values, baking in
rank-specific embedding vocab offsets.
- compile.py: Mode-aware validation (aot_fx_trace doesn't need
serializable passes), logging for precompile load vs runtime trace
- trainer.py: _load_precompiled_fx_trace(), branching in
_make_fx_forward_backward_step()
- make_fx_tracer.py: Use set_multithreading_enabled(False) so backward
tracing runs on the calling thread, keeping the compile_on_one_rank
ContextVar visible
- cudagraph.py: Defer _input_indices_to_copy when example_inputs is
empty (precompile load path), accept opaque values (DeviceMesh) in
input validation, skip non-tensors in static address checks.
Squashed the separate cudagraph CooR PR into this one because
cudagraph activates automatically for aot_fx_trace graphs (all
inputs are desugared plain tensors + opaques, no HOPs), so bitwise
equivalence testing required both fixes together.
- passes.py: Guard cudagraph_pass against non-GraphModule inputs
Test plan:
- pytest torchtitan/experiments/graph_trainer/tests/test_bitwise_deterministic.py -x
— 6 passed, 4 skipped (Llama3, DSv3 × {eager self-deterministic,
eager vs aot_fx_trace, precompile vs trace})
- pytest torchtitan/experiments/graph_trainer/tests/test_precompile.py -x — all pass
- pytest torchtitan/experiments/graph_trainer/tests/test_trace_module.py -x — all pass
- 8-GPU integration tests via CI (ciflow/8gpu)
ghstack-source-id: 509c94b
Pull-Request: #2975
bobrenjc93
added a commit
that referenced
this pull request
Apr 16, 2026
…mode
Introduce aot_fx_trace as an alternate precompilation path alongside
the existing AOT joint graph export. aot_fx_trace uses make_fx to
trace the full fwd+loss+bwd step as a single FX graph, then serializes
the GraphModule for loading on all ranks during training.
Key differences from AOT precompile:
- Traces fwd+loss+bwd together (no AOTAutograd partitioning)
- Serializes the FX graph, not compiled Triton kernels
- Inductor compilation happens at load time on each rank
- No pipeline parallel support (no graph partitioning)
Changes:
- precompile_main.py: Refactor into _common_setup() + _precompile_aot()
+ _precompile_aot_fx_trace(), route by --compile.mode. Use Python
float for global_valid_tokens (matching dist_sum's return type) so
make_fx bakes it as a graph constant, identical to the runtime path.
- precompile.py: PrecompiledFxTraceArtifact dataclass, save/load fns.
Uses GraphPickler (not plain pickle) to preserve SymInt expressions
(_runtime_compute_coordinate_on_dim) through serialization — plain
pickle evaluates SymInts to concrete trace-time values, baking in
rank-specific embedding vocab offsets.
- compile.py: Mode-aware validation (aot_fx_trace doesn't need
serializable passes), logging for precompile load vs runtime trace
- trainer.py: _load_precompiled_fx_trace(), branching in
_make_fx_forward_backward_step()
- make_fx_tracer.py: Use set_multithreading_enabled(False) so backward
tracing runs on the calling thread, keeping the compile_on_one_rank
ContextVar visible
- cudagraph.py: Defer _input_indices_to_copy when example_inputs is
empty (precompile load path), accept opaque values (DeviceMesh) in
input validation, skip non-tensors in static address checks.
Squashed the separate cudagraph CooR PR into this one because
cudagraph activates automatically for aot_fx_trace graphs (all
inputs are desugared plain tensors + opaques, no HOPs), so bitwise
equivalence testing required both fixes together.
- passes.py: Guard cudagraph_pass against non-GraphModule inputs
Test plan:
- pytest torchtitan/experiments/graph_trainer/tests/test_bitwise_deterministic.py -x
— 6 passed, 4 skipped (Llama3, DSv3 × {eager self-deterministic,
eager vs aot_fx_trace, precompile vs trace})
- pytest torchtitan/experiments/graph_trainer/tests/test_precompile.py -x — all pass
- pytest torchtitan/experiments/graph_trainer/tests/test_trace_module.py -x — all pass
- 8-GPU integration tests via CI (ciflow/8gpu)
ghstack-source-id: 8541884
Pull-Request: #2975
bobrenjc93
added a commit
that referenced
this pull request
Apr 16, 2026
…mode
Introduce aot_fx_trace as an alternate precompilation path alongside
the existing AOT joint graph export. aot_fx_trace uses make_fx to
trace the full fwd+loss+bwd step as a single FX graph, then serializes
the GraphModule for loading on all ranks during training.
Key differences from AOT precompile:
- Traces fwd+loss+bwd together (no AOTAutograd partitioning)
- Serializes the FX graph, not compiled Triton kernels
- Inductor compilation happens at load time on each rank
- No pipeline parallel support (no graph partitioning)
Changes:
- precompile_main.py: Refactor into _common_setup() + _precompile_aot()
+ _precompile_aot_fx_trace(), route by --compile.mode. Use Python
float for global_valid_tokens (matching dist_sum's return type) so
make_fx bakes it as a graph constant, identical to the runtime path.
- precompile.py: PrecompiledFxTraceArtifact dataclass, save/load fns.
Uses GraphPickler (not plain pickle) to preserve SymInt expressions
(_runtime_compute_coordinate_on_dim) through serialization — plain
pickle evaluates SymInts to concrete trace-time values, baking in
rank-specific embedding vocab offsets.
- compile.py: Mode-aware validation (aot_fx_trace doesn't need
serializable passes), logging for precompile load vs runtime trace
- trainer.py: _load_precompiled_fx_trace(), branching in
_make_fx_forward_backward_step()
- make_fx_tracer.py: Use set_multithreading_enabled(False) so backward
tracing runs on the calling thread, keeping the compile_on_one_rank
ContextVar visible
- cudagraph.py: Defer _input_indices_to_copy when example_inputs is
empty (precompile load path), accept opaque values (DeviceMesh) in
input validation, skip non-tensors in static address checks.
Squashed the separate cudagraph CooR PR into this one because
cudagraph activates automatically for aot_fx_trace graphs (all
inputs are desugared plain tensors + opaques, no HOPs), so bitwise
equivalence testing required both fixes together.
- passes.py: Guard cudagraph_pass against non-GraphModule inputs
Test plan:
- pytest torchtitan/experiments/graph_trainer/tests/test_bitwise_deterministic.py -x
— 6 passed, 4 skipped (Llama3, DSv3 × {eager self-deterministic,
eager vs aot_fx_trace, precompile vs trace})
- pytest torchtitan/experiments/graph_trainer/tests/test_precompile.py -x — all pass
- pytest torchtitan/experiments/graph_trainer/tests/test_trace_module.py -x — all pass
- 8-GPU integration tests via CI (ciflow/8gpu)
ghstack-source-id: 80c1fad
Pull-Request: #2975
SherlockNoMad
approved these changes
Apr 16, 2026
Contributor
|
Do we have clear instruction in claude.md for agent to use the pre-compile workflow? I would validate by prompting ”run graph_trainer precompile training of llama_8b for me, show me the MFU, profiling result and memory snapshot as proof of work" in a /new session. this should work in one shot. |
bobrenjc93
added a commit
that referenced
this pull request
Apr 16, 2026
…mode
Introduce aot_fx_trace as an alternate precompilation path alongside
the existing AOT joint graph export. aot_fx_trace uses make_fx to
trace the full fwd+loss+bwd step as a single FX graph, then serializes
the GraphModule for loading on all ranks during training.
Key differences from AOT precompile:
- Traces fwd+loss+bwd together (no AOTAutograd partitioning)
- Serializes the FX graph, not compiled Triton kernels
- Inductor compilation happens at load time on each rank
- No pipeline parallel support (no graph partitioning)
Changes:
- precompile_main.py: Refactor into _common_setup() + _precompile_aot()
+ _precompile_aot_fx_trace(), route by --compile.mode. Use Python
float for global_valid_tokens (matching dist_sum's return type) so
make_fx bakes it as a graph constant, identical to the runtime path.
- precompile.py: PrecompiledFxTraceArtifact dataclass, save/load fns.
Uses GraphPickler (not plain pickle) to preserve SymInt expressions
(_runtime_compute_coordinate_on_dim) through serialization — plain
pickle evaluates SymInts to concrete trace-time values, baking in
rank-specific embedding vocab offsets.
- compile.py: Mode-aware validation (aot_fx_trace doesn't need
serializable passes), logging for precompile load vs runtime trace
- trainer.py: _load_precompiled_fx_trace(), branching in
_make_fx_forward_backward_step()
- make_fx_tracer.py: Use set_multithreading_enabled(False) so backward
tracing runs on the calling thread, keeping the compile_on_one_rank
ContextVar visible
- cudagraph.py: Defer _input_indices_to_copy when example_inputs is
empty (precompile load path), accept opaque values (DeviceMesh) in
input validation, skip non-tensors in static address checks.
Squashed the separate cudagraph CooR PR into this one because
cudagraph activates automatically for aot_fx_trace graphs (all
inputs are desugared plain tensors + opaques, no HOPs), so bitwise
equivalence testing required both fixes together.
- passes.py: Guard cudagraph_pass against non-GraphModule inputs
Test plan:
- pytest torchtitan/experiments/graph_trainer/tests/test_bitwise_deterministic.py -x
— 6 passed, 4 skipped (Llama3, DSv3 × {eager self-deterministic,
eager vs aot_fx_trace, precompile vs trace})
- pytest torchtitan/experiments/graph_trainer/tests/test_precompile.py -x — all pass
- pytest torchtitan/experiments/graph_trainer/tests/test_trace_module.py -x — all pass
- 8-GPU integration tests via CI (ciflow/8gpu)
ghstack-source-id: 80c1fad
Pull-Request: #2975
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Stack from ghstack (oldest at bottom):
Introduce aot_fx_trace as an alternate precompilation path alongside
the existing AOT joint graph export. aot_fx_trace uses make_fx to
trace the full fwd+loss+bwd step as a single FX graph, then serializes
the GraphModule for loading on all ranks during training. Because
cudagraphs is a default pass, we also include cudagraph composability
related changes in this PR to get to bitwise equivalence between
aot_fx_trace with and without precompile.
Changes:
float for global_valid_tokens (matching dist_sum's return type) so
make_fx bakes it as a graph constant, identical to the runtime path.
Uses GraphPickler (not plain pickle) to preserve SymInt expressions
(_runtime_compute_coordinate_on_dim) through serialization — plain
pickle evaluates SymInts to concrete trace-time values, baking in
rank-specific embedding vocab offsets.
serializable passes), logging for precompile load vs runtime trace
_make_fx_forward_backward_step()
tracing runs on the calling thread, keeping the compile_on_one_rank
ContextVar visible
empty (precompile load path), accept opaque values (DeviceMesh) in
input validation, skip non-tensors in static address checks.
Squashed the separate cudagraph CooR PR into this one because
cudagraph activates automatically for aot_fx_trace graphs (all
inputs are desugared plain tensors + opaques, no HOPs), so bitwise
equivalence testing required both fixes together.
Test plan
pytest torchtitan/experiments/graph_trainer/tests/test_bitwise_deterministic.py -x— 6 passed, 4 skipped (Llama3, DSv3 × {eager self-deterministic, eager vs aot_fx_trace, precompile vs trace})pytest torchtitan/experiments/graph_trainer/tests/test_precompile.py -x— all passpytest torchtitan/experiments/graph_trainer/tests/test_trace_module.py -x— all pass