Repository navigation
[None][perf] Autotuner: distributed tuning for mhc + single-(runner,tactic) shortcut - #14458
Conversation
|
/bot run --disable-fail-fast --add-multi-gpu-test |
|
PR_Github #50135 [ run ] triggered by Bot. Commit: |
|
PR_Github #50135 [ run ] completed with state
|
|
/bot run --disable-fail-fast --add-multi-gpu-test |
|
PR_Github #50180 [ run ] triggered by Bot. Commit: |
|
PR_Github #50180 [ run ] completed with state
|
391d28f to
8e9770a
Compare
|
/bot run --disable-fail-fast --add-multi-gpu-test |
|
PR_Github #50248 [ run ] triggered by Bot. Commit: |
|
PR_Github #50248 [ run ] completed with state
|
|
/bot run --disable-fail-fast --add-multi-gpu-test |
|
PR_Github #50332 [ run ] triggered by Bot. Commit: |
|
PR_Github #50332 [ run ] completed with state |
bbe1b25 to
4e942f3
Compare
|
/bot run --disable-fail-fast --add-multi-gpu-test |
4e942f3 to
83241b9
Compare
|
PR_Github #50483 [ run ] triggered by Bot. Commit: |
…actic) shortcut
Two related refinements for JIT-driven custom ops (DeepGEMM, Triton,
CuteDSL) in the autotuner.
1. New TuningConfig.exclude_from_cache flag, default False.
For JIT-driven ops (e.g. fp8_swap_ab_gemm with DeepGEMM) the tuning
call itself is what triggers JIT compilation as a side effect.
Persisting the chosen tactic across process startups skips the
tuning path on the next run, so the JIT never warms up and the first
inference request pays the compile cost on the critical path.
When exclude_from_cache=True:
- choose_one forces a re-tune in tuning mode (drives the JIT
warmup as a side effect)
- the in-process cache still works for subsequent calls within
the same process
- _partition_cache_by_strategy drops the op from disk persistence
Applied to fp8SwapABGemmRunner.tuning_config (the reported case).
2. Single-(runner, tactic) shortcut in _profile_runners.
When a custom_op exposes exactly one candidate (runner, tactic) pair
across all runners, there is nothing to compare against. The warmup
+ profile-repeat loop in _profile_single_kernel is pure overhead --
typical for JIT-driven kernels whose only purpose for the tuning
round-trip is to fire the JIT compile as a side effect.
The shortcut fires exactly one forward() call (no timing, no warmup
loop) and records the (runner, tactic) pair directly in the
profiling cache. do_preparation hooks (e.g. AllReduceRunner buffer
pre-allocation) still fire.
The total-pair count is computed BEFORE distributed-strategy
splitting so the PARALLEL strategy -- which can leave a rank with
one tactic locally even though the full set has several -- still
goes through the timed profile path so the merge picks a real
winner.
For fp8SwapABGemmRunner this reduces per-shape-bucket warmup from
~5+ forward calls to 1.
UT coverage (tests/unittest/_torch/misc/test_autotuner.py):
- test_single_tactic_skips_profile_kernel
- test_multi_tactic_still_invokes_profile_kernel
- test_single_tactic_do_preparation_still_fires
- test_single_tactic_records_cache_entry
- test_single_tactic_across_multiple_runners_takes_normal_path
Signed-off-by: Yukun He <23156053+hyukn@users.noreply.github.com>
MhcPreMappingRunner.tuning_config and MhcFusedHcRunner.tuning_config both expose multi-tactic tuning spaces. Switching their distributed_tuning_strategy from the default INDEPENDENT to PARALLEL fans the tactic list out across TP ranks (each rank times a disjoint subset, _merge_cache_data picks the global best). With dsv4 ranks at TP=4, this collapses the MhcPreMapping span from ~5-6 min to ~2 min and MhcFusedHc from ~2 min to a few seconds, with no change in the chosen tactic. Signed-off-by: Yukun He <23156053+hyukn@users.noreply.github.com>
83241b9 to
66c81a0
Compare
|
/bot run --disable-fail-fast --add-multi-gpu-test |
|
PR_Github #50490 [ run ] triggered by Bot. Commit: |
|
PR_Github #50483 [ run ] completed with state |
|
PR_Github #50490 [ run ] completed with state |
PR NVIDIA#14458 enabled `distributed_tuning_strategy=DistributedTuningStrategy.PARALLEL` on both MhcPreMappingRunner and MhcFusedHcRunner. The MhcFusedHc setting triggers a non-deterministic CUDA Illegal Memory Access on TP=8 disagg GEN workers during the post-autotune max-batch CUDA-graph capture (observed on the 1024-1024 disagg_ctx1_gen1_tep8_batch256 recipe and the 8192-1024 disagg_ctx1_gen1_dep8_batch512 recipe; ~67% crash rate across 3 reruns of the same config). Mechanism: MhcFusedHcRunner has a per-instance LRU workspace cache (`_FusedHcWorkspaceCache`) keyed on `(B, num_k_splits, tile_m, device)` — all derived from the chosen tactic. Under PARALLEL, each rank measures only `idx % tp_size == tp_rank` of the tactics, so each rank's LRU ends up populated with workspace entries for a different tactic subset. After `_merge_cache_data` writes the global-best tactic to the autotuner cache, ranks that didn't locally measure that tactic hit a workspace-cache miss and call `torch.empty(...)` fresh — inside the post-autotune CUDA-graph-capture region for the max-batch warmup step. Fresh allocations are incompatible with capture; the next collective kernel (MLA attention) dereferences a stale/uncaptured pointer → IMA on the cache-miss rank (rank 6 at TP=8 in the observed cases). MhcPreMappingRunner does NOT have this problem: its forward() uses fresh `torch.empty(...)` every call, keyed only on `(M, n, hidden_size)`, independent of the chosen tactic. So per-rank tactic-subset profiling under PARALLEL produces identical allocation histories across ranks. Per-op cost data on this disagg recipe shows MhcFusedHc PARALLEL adds ~no autotune saving (GEN: 4m 42s with both PARALLEL vs 4m 46s with only MhcPre PARALLEL — within JIT noise), so dropping it is a clean revert with no perf cost. MhcPre PARALLEL still buys ~27% CTX autotune reduction on the same recipe. A/B/C/D variant matrix at TP=8 disagg (3 nodes, max_batch=256): - MhcPre=ON, MhcFused=ON (A): IMA in 2/3 reruns - MhcPre=OFF, MhcFused=OFF (B): clean - MhcPre=OFF, MhcFused=ON (C): IMA - MhcPre=ON, MhcFused=OFF (D): clean ← this PR's configuration Re-enabling MhcFusedHc PARALLEL is a follow-up after the workspace LRU is reworked (e.g. by dropping tactic-dependent keying, or by harmonizing the LRU across ranks post-merge). Signed-off-by: Yukun He <23156053+hyukn@users.noreply.github.com>
…actic) shortcut (NVIDIA#14458) Signed-off-by: Yukun He <23156053+hyukn@users.noreply.github.com>
…actic) shortcut (NVIDIA#14458) Signed-off-by: Yukun He <23156053+hyukn@users.noreply.github.com>
…actic) shortcut (NVIDIA#14458) Signed-off-by: Yukun He <23156053+hyukn@users.noreply.github.com>
…actic) shortcut (NVIDIA#14458) Signed-off-by: Yukun He <23156053+hyukn@users.noreply.github.com> (cherry picked from commit 5d59d34)
Summary
Three refinements for JIT-driven custom ops (DeepGEMM, Triton, CuteDSL) and multi-tactic MHC ops in the autotuner:
TuningConfig.exclude_from_cacheflag (defaultFalse). For JIT-driven ops, the tuning call itself triggers JIT compilation as a side effect. Persisting the chosen tactic across process startups skips the tuning path on the next run, so the JIT never warms up and the first inference request pays the compile cost on the critical path. The flag tells the autotuner to:_partition_cache_by_strategy.Applied to
fp8SwapABGemmRunner.tuning_config.Single-(runner, tactic) shortcut in
_profile_runners. When an op exposes exactly one candidate pair across all runners, there is nothing to compare against. The warmup + profile-repeat loop in_profile_single_kernelis pure overhead for JIT-driven kernels whose only purpose for the round-trip is firing the JIT compile. The shortcut fires oneforward()call (no timing, no warmup loop) and records the pair directly.do_preparationstill fires.Total-pair count is computed BEFORE distributed-strategy splitting so
PARALLEL— which can leave a rank with one tactic locally while the full set has several — still goes through the timed path so the merge picks a real winner.For
fp8SwapABGemmRunnerthis reduces per-shape-bucket warmup from ~5+ forward calls to 1.Switch MHC ops to
DistributedTuningStrategy.PARALLEL.MhcPreMappingRunnerandMhcFusedHcRunnerboth expose multi-tactic spaces. Fanning their tactics out across TP ranks (each rank times a disjoint subset, then merge picks the global best) collapses the MhcPreMapping tuning span from ~5–6 min to ~2 min and MhcFusedHc from ~2 min to a few seconds with no change in the chosen tactic.End-to-end measurements (cold autotune, no autotuner/DG cache, dsv4-325152 container, Pro 16K recipe, dataset 1024-1-20000-ratio-08):
Tactic-choice agreement vs INDEPENDENT reference at TEP8 (per-shape comparison, 627 unique shapes):
🤖 Generated with Claude Code