[#13718][feat] AutoDeploy MoE all-to-all: cache + runtime max-tokens - #13723
Conversation
|
/bot run --extra-stage "DGX_B200-4_GPUs-AutoDeploy-1, DGX_H100-4_GPUs-AutoDeploy-1" |
|
PR_Github #46644 [ run ] triggered by Bot. Commit: |
📝 WalkthroughWalkthroughThis PR implements a stateful MoE all-to-all cache and runtime max-tokens feature. ChangesDP-Aware Batch Info and MoE All-to-All Caching
Sequence DiagramsequenceDiagram
participant AD as ADEngine
participant Gath as tp_allgather
participant Batch as BatchInfo
participant Cache as _GlobalMoeA2ACache
participant Runner as _run_moe_with_alltoall
participant A2A as MoeAlltoAll
AD->>AD: Collect local_num_tokens per rank
AD->>Gath: tp_allgather(local_num_tokens)
Gath-->>AD: all_rank_num_tokens[]
AD->>AD: max_dp = max(all_rank_num_tokens)
AD->>Batch: update_max_dp_num_tokens(max_dp)
Note over Batch: batch_info_host[13] = max_dp
AD->>Runner: Call with batch_info_host tensor
Runner->>Runner: Extract runtime_max = batch_info_host[13]
Runner->>Cache: get_alltoall(mapping, ...)
alt Cache Hit
Cache-->>A2A: Return cached instance
else Cache Miss
Cache->>A2A: Create new MoeAlltoAll(...)
Cache-->>A2A: Cache & return
end
Runner->>A2A: run_dispatch(runtime_max_tokens_per_rank=runtime_max)
A2A-->>Runner: Padded output
Runner-->>AD: Result
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
tensorrt_llm/_torch/auto_deploy/shim/ad_executor.py (1)
966-978: ⚡ Quick winAdd targeted unit coverage for the slot-13 override gate.
Please add tests for both branches:
(enable_attention_dp=True, tp_size>1)writes cross-rank max, and fallback path keeps local total. This is the key correctness contract for the new runtime padding behavior.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tensorrt_llm/_torch/auto_deploy/shim/ad_executor.py` around lines 966 - 978, Add unit tests in the ad_executor test suite that exercise the slot-13 override gate around attention DP: create one test where ad_executor.enable_attention_dp=True and ad_executor.dist_config.tp_size>1 and mock ad_executor.dist.tp_allgather to return different per-rank totals so that cache_seq_interface.info.batch_info.update_max_dp_num_tokens is called with the cross-rank max (verify call and stored value using the batch_info getter); create another test where either enable_attention_dp=False or tp_size==1 and assert that update_max_dp_num_tokens is not invoked and the original local total from cache_seq_interface.info.batch_info.get_total_num_tokens remains unchanged. Ensure mocks/stubs target the methods dist.tp_allgather, cache_seq_interface.info.batch_info.get_total_num_tokens, and cache_seq_interface.info.batch_info.update_max_dp_num_tokens to observe behavior.tensorrt_llm/_torch/auto_deploy/custom_ops/fused_moe/torch_moe.py (1)
276-291: ⚡ Quick winThread
batch_info_hostthrough_template_moe()too.The new arg is accepted by the public op signature, but this path still drops it before
_template_moe()/_template_moe_alltoall(), so the torch all-to-all backend keeps padding from staticmax_num_tokens. That leaves eager/reference runs on the old behavior even though sharding now wires the host-side runtime value into the graph.Also applies to: 343-351
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tensorrt_llm/_torch/auto_deploy/custom_ops/fused_moe/torch_moe.py` around lines 276 - 291, The public op torch_moe now accepts batch_info_host but drops it before calling the internal runners; update torch_moe to pass batch_info_host through to _template_moe (and where applicable to _template_moe_alltoall) so the internal implementations receive the host-side runtime value instead of using static max_num_tokens; locate calls to _template_moe/_template_moe_alltoall in torch_moe and append the batch_info_host argument (and mirror the change for the similar call paths around the other occurrence noted at lines 343-351) so both all-to-all and non-all-to-all branches forward the parameter.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@tensorrt_llm/_torch/auto_deploy/custom_ops/fused_moe/trtllm_moe.py`:
- Around line 220-245: After reading runtime_max_tokens_per_rank from
batch_info_host, validate and clamp it to the workspace upper bound
(max_num_tokens) to avoid indexing/size mismatches with the cached MoeAlltoAll
instance; i.e., if runtime_max_tokens_per_rank <= 0 set to max_num_tokens as
already done, and additionally if runtime_max_tokens_per_rank > max_num_tokens
reset it to max_num_tokens (optionally emit a warning). Apply the same
clamping/validation wherever runtime_max_tokens_per_rank is derived and later
passed into dispatch()/combine() or used for padding (the code paths around the
runtime_max_tokens_per_rank variable and the call to
_GlobalMoeA2ACache.get_alltoall and subsequent dispatch/combine).
---
Nitpick comments:
In `@tensorrt_llm/_torch/auto_deploy/custom_ops/fused_moe/torch_moe.py`:
- Around line 276-291: The public op torch_moe now accepts batch_info_host but
drops it before calling the internal runners; update torch_moe to pass
batch_info_host through to _template_moe (and where applicable to
_template_moe_alltoall) so the internal implementations receive the host-side
runtime value instead of using static max_num_tokens; locate calls to
_template_moe/_template_moe_alltoall in torch_moe and append the batch_info_host
argument (and mirror the change for the similar call paths around the other
occurrence noted at lines 343-351) so both all-to-all and non-all-to-all
branches forward the parameter.
In `@tensorrt_llm/_torch/auto_deploy/shim/ad_executor.py`:
- Around line 966-978: Add unit tests in the ad_executor test suite that
exercise the slot-13 override gate around attention DP: create one test where
ad_executor.enable_attention_dp=True and ad_executor.dist_config.tp_size>1 and
mock ad_executor.dist.tp_allgather to return different per-rank totals so that
cache_seq_interface.info.batch_info.update_max_dp_num_tokens is called with the
cross-rank max (verify call and stored value using the batch_info getter);
create another test where either enable_attention_dp=False or tp_size==1 and
assert that update_max_dp_num_tokens is not invoked and the original local total
from cache_seq_interface.info.batch_info.get_total_num_tokens remains unchanged.
Ensure mocks/stubs target the methods dist.tp_allgather,
cache_seq_interface.info.batch_info.get_total_num_tokens, and
cache_seq_interface.info.batch_info.update_max_dp_num_tokens to observe
behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: ce766138-1807-4fef-bd54-530e18fa1873
📒 Files selected for processing (5)
tensorrt_llm/_torch/auto_deploy/custom_ops/attention_interface.pytensorrt_llm/_torch/auto_deploy/custom_ops/fused_moe/torch_moe.pytensorrt_llm/_torch/auto_deploy/custom_ops/fused_moe/trtllm_moe.pytensorrt_llm/_torch/auto_deploy/shim/ad_executor.pytensorrt_llm/_torch/auto_deploy/transform/library/sharding.py
|
PR_Github #46644 [ run ] completed with state
|
|
/bot run --extra-stage "DGX_B200-4_GPUs-AutoDeploy-1, DGX_H100-4_GPUs-AutoDeploy-1" --disable-fail-fast |
|
PR_Github #46801 [ run ] triggered by Bot. Commit: |
|
PR_Github #46801 [ run ] completed with state |
a17bc36 to
1fe8a39
Compare
|
/bot run --extra-stage "DGX_B200-4_GPUs-AutoDeploy-1, DGX_H100-4_GPUs-AutoDeploy-1" --disable-fail-fast |
|
/bot run --extra-stage "DGX_B200-4_GPUs-AutoDeploy-1, DGX_H100-4_GPUs-AutoDeploy-1" |
|
PR_Github #47035 [ run ] triggered by Bot. Commit: |
|
PR_Github #47035 [ run ] completed with state
|
|
/bot run --extra-stage "DGX_B200-4_GPUs-AutoDeploy-1, DGX_H100-4_GPUs-AutoDeploy-1" --disable-fail-fast |
|
PR_Github #47189 [ run ] triggered by Bot. Commit: |
|
could we also test with deepseek R1? |
|
PR_Github #47189 [ run ] completed with state
|
1fe8a39 to
3afaa2e
Compare
|
/bot run --extra-stage "DGX_B200-4_GPUs-AutoDeploy-1, DGX_H100-4_GPUs-AutoDeploy-1" --disable-fail-fast --post-merge |
|
PR_Github #52050 [ run ] triggered by Bot. Commit: |
|
/bot run --extra-stage "DGX_B200-4_GPUs-AutoDeploy-1, DGX_H100-4_GPUs-AutoDeploy-1" --disable-fail-fast --post-merge |
|
PR_Github #52074 [ run ] triggered by Bot. Commit: |
|
PR_Github #52050 [ run ] completed with state |
|
PR_Github #52074 [ run ] completed with state
|
greg-kwasniewski1
left a comment
There was a problem hiding this comment.
as discussed, @MrGeva , ok with the current status?
|
/bot skip --comment "AutoDeploy multi-GPU CI clean on pipeline #41405: 0 AD failures across DGX_H100-4_GPUs-AutoDeploy-{1,Post-Merge-1} and DGX_B200-4_GPUs-AutoDeploy-1. MoE+ADP validation: TestNemotronNanoV3::test_accuracy[fp8-4-attn_dp_on-trtllm] PASSED" |
|
PR_Github #52395 [ skip ] triggered by Bot. Commit: |
|
PR_Github #52395 [ skip ] completed with state |
…okens Squashed history of PR NVIDIA#13723. Stateful MoeAlltoAll cache + runtime cross-rank max-token awareness fixes the conc=32 NaN regression under attention-DP. Core changes: - trtllm_moe.py: _MoeAll2AllCache singleton (avoid Python ctor + JSON deserialization per-layer per-step); read max_dp_num_tokens from batch_info_host at capture time instead of the conservative config-level max_num_tokens upper bound. - attention_interface.py: BatchInfo slot 14 = max_dp_num_tokens. - cuda_graph.py + torch_cudagraph.py: BypassCapturedGraphs context + cuda_graph_state.BYPASS flag for cross-rank divergence fallback. - ad_executor.py: cross-rank vote via tp_allgather; bypass when any rank is eager; write max_dp_num_tokens pre-forward. - sharding.py / sharding_ir.py: wire batch_info_host placeholder into graph for both legacy and IR transform paths (mutually exclusive by config). - fuse_quant.py: kwargs-only FP8/FP4 ref replacements (FX robustness against sharding placeholder insertion). - torch_moe.py / interface.py: signature + placeholder plumbing. Tests: - test_bypass_captured_graphs.py: NEW 2-GPU regression test covering bypass mechanism in 4 scenarios. - TestNemotronNanoV3.test_accuracy parametrized with enable_attention_dp; mechanical ID rename across test-db YAMLs and qa/llm_function_core.txt. - waives.txt: remove 2 stale [-trtllm] NanoV3 waives (6185150) whose IDs no longer exist after parametrization. - l0_dgx_{b200,h100}.yml: NVBUG-6221483 tests deferred to post-merge (intentional retention of bca66aa's effect). Signed-off-by: greg-kwasniewski1 <213329731+greg-kwasniewski1@users.noreply.github.com>
161c85d to
2f5e6af
Compare
|
/bot skip --comment "AutoDeploy multi-GPU CI clean on pipeline #41405: 0 AD failures across DGX_H100-4_GPUs-AutoDeploy-{1,Post-Merge-1} and DGX_B200-4_GPUs-AutoDeploy-1. MoE+ADP validation: TestNemotronNanoV3::test_accuracy[fp8-4-attn_dp_on-trtllm] PASSED" |
|
PR_Github #52570 [ skip ] triggered by Bot. Commit: |
|
PR_Github #52570 [ skip ] completed with state |
…mization Rebases the SuperV3-MTP attention-DP optimization onto current upstream/main (which now carries gk's MoE all-to-all stateful cache NVIDIA#13718/NVIDIA#13723 and gagam's SSM-replay PR). All net changes from the optimization branch are preserved. MoE all-to-all per-rank token budget (runtime_max_tokens_per_rank): - Replace the per-iteration cross-rank-max read (an int(batch_info_host[14] .item()) on a pinned-host tensor, fed by a per-forward tp_allgather) with a sync-free shape-based budget via _hybrid_runtime_max_tokens_per_rank: under cuda-graph capture/warm-up the budget is x.shape[0] (uniform across DP ranks because maybe_pad_for_cuda_graph pads every rank to a common cg_batch_size and MTP tokens-per-seq is uniform), gated so the tight budget is only taken while the MoE-GEMM row count stays in the fast small-M tactic region; in eager (prefill or bypass) it falls back to the static max_num_tokens every rank computes identically. No per-layer host read. - Drop the now-dead batch_info_host plumbing for the DP-max slot: the slot-14 (max_dp_num_tokens) storage and update/get accessors in BatchInfo (_NUM_ELEMENTS 15->14), the pre-forward tp_allgather + update in the AD shim, and the batch_info_host injection into the MoE op in both the dict-based (sharding.py) and IR-based (sharding_ir.py) sharding paths, plus the op signatures in trtllm_moe.py / torch_moe.py. Scheduling / sharding: - Enable the attention-DP request balancer (PyExecutor._balance_adp_requests) in the AD executor so prefill is co-scheduled across ranks, avoiding a single prefill straggler stalling the others at the MoE all-to-all collective. - Keep the draft-EP revert under attention-DP in sharding (replicate the draft model's MoE rather than EP-sharding it) to avoid the shared-workspace corruption that hangs the all-to-all at concurrency. Mixed-mode cuda-graph bypass uses upstream's process-wide BypassCapturedGraphs() context manager (cuda_graph_state.in_bypass()) instead of the per-instance flag, keeping all ranks consistent when one is in prefill. Tests: - Add NVFP4 SuperV3-MTP attn-DP perf-sanity config + post-merge enrollment. - test_mtp / test_accuracy NVFP4 coverage resolved to upstream's parametrization. Signed-off-by: Eran Geva <19514940+MrGeva@users.noreply.github.com>
…mization Rebases the SuperV3-MTP attention-DP optimization onto current upstream/main (which now carries gk's MoE all-to-all stateful cache NVIDIA#13718/NVIDIA#13723 and gagam's SSM-replay PR). All net changes from the optimization branch are preserved. MoE all-to-all per-rank token budget (runtime_max_tokens_per_rank): - Replace the per-iteration cross-rank-max read (an int(batch_info_host[14] .item()) on a pinned-host tensor, fed by a per-forward tp_allgather) with a sync-free shape-based budget via _hybrid_runtime_max_tokens_per_rank: under cuda-graph capture/warm-up the budget is x.shape[0] (uniform across DP ranks because maybe_pad_for_cuda_graph pads every rank to a common cg_batch_size and MTP tokens-per-seq is uniform), gated so the tight budget is only taken while the MoE-GEMM row count stays in the fast small-M tactic region; in eager (prefill or bypass) it falls back to the static max_num_tokens every rank computes identically. No per-layer host read. - Drop the now-dead batch_info_host plumbing for the DP-max slot: the slot-14 (max_dp_num_tokens) storage and update/get accessors in BatchInfo (_NUM_ELEMENTS 15->14), the pre-forward tp_allgather + update in the AD shim, and the batch_info_host injection into the MoE op in both the dict-based (sharding.py) and IR-based (sharding_ir.py) sharding paths, plus the op signatures in trtllm_moe.py / torch_moe.py. Scheduling / sharding: - Enable the attention-DP request balancer (PyExecutor._balance_adp_requests) in the AD executor so prefill is co-scheduled across ranks, avoiding a single prefill straggler stalling the others at the MoE all-to-all collective. - Keep the draft-EP revert under attention-DP in sharding (replicate the draft model's MoE rather than EP-sharding it) to avoid the shared-workspace corruption that hangs the all-to-all at concurrency. Mixed-mode cuda-graph bypass uses upstream's process-wide BypassCapturedGraphs() context manager (cuda_graph_state.in_bypass()) instead of the per-instance flag, keeping all ranks consistent when one is in prefill. Tests: - Add NVFP4 SuperV3-MTP attn-DP perf-sanity config + post-merge enrollment. - test_mtp / test_accuracy NVFP4 coverage resolved to upstream's parametrization. Signed-off-by: Eran Geva <19514940+MrGeva@users.noreply.github.com>
…mization Rebases the SuperV3-MTP attention-DP optimization onto current upstream/main (which now carries gk's MoE all-to-all stateful cache NVIDIA#13718/NVIDIA#13723 and gagam's SSM-replay PR). All net changes from the optimization branch are preserved. MoE all-to-all per-rank token budget (runtime_max_tokens_per_rank): - Replace the per-iteration cross-rank-max read (an int(batch_info_host[14] .item()) on a pinned-host tensor, fed by a per-forward tp_allgather) with a sync-free shape-based budget via _hybrid_runtime_max_tokens_per_rank: under cuda-graph capture/warm-up the budget is x.shape[0] (uniform across DP ranks because maybe_pad_for_cuda_graph pads every rank to a common cg_batch_size and MTP tokens-per-seq is uniform), gated so the tight budget is only taken while the MoE-GEMM row count stays in the fast small-M tactic region; in eager (prefill or bypass) it falls back to the static max_num_tokens every rank computes identically. No per-layer host read. - Drop the now-dead batch_info_host plumbing for the DP-max slot: the slot-14 (max_dp_num_tokens) storage and update/get accessors in BatchInfo (_NUM_ELEMENTS 15->14), the pre-forward tp_allgather + update in the AD shim, and the batch_info_host injection into the MoE op in both the dict-based (sharding.py) and IR-based (sharding_ir.py) sharding paths, plus the op signatures in trtllm_moe.py / torch_moe.py. Scheduling / sharding: - Enable the attention-DP request balancer (PyExecutor._balance_adp_requests) in the AD executor so prefill is co-scheduled across ranks, avoiding a single prefill straggler stalling the others at the MoE all-to-all collective. - Keep the draft-EP revert under attention-DP in sharding (replicate the draft model's MoE rather than EP-sharding it) to avoid the shared-workspace corruption that hangs the all-to-all at concurrency. Mixed-mode cuda-graph bypass uses upstream's process-wide BypassCapturedGraphs() context manager (cuda_graph_state.in_bypass()) instead of the per-instance flag, keeping all ranks consistent when one is in prefill. Tests: - Add NVFP4 SuperV3-MTP attn-DP perf-sanity config + post-merge enrollment. - test_mtp / test_accuracy NVFP4 coverage resolved to upstream's parametrization. Signed-off-by: Eran Geva <19514940+MrGeva@users.noreply.github.com>
…okens (NVIDIA#13723) Signed-off-by: greg-kwasniewski1 <213329731+greg-kwasniewski1@users.noreply.github.com>
…mization Rebases the SuperV3-MTP attention-DP optimization onto current upstream/main (which now carries gk's MoE all-to-all stateful cache NVIDIA#13718/NVIDIA#13723 and gagam's SSM-replay PR). MoE all-to-all per-rank token budget (runtime_max_tokens_per_rank): - Replace the per-iteration cross-rank-max read (an int(batch_info_host[14] .item()) on a pinned-host tensor, fed by a per-forward tp_allgather) with a sync-free shape-based budget via _hybrid_runtime_max_tokens_per_rank: under cuda-graph capture/warm-up the budget is x.shape[0] (uniform across DP ranks because maybe_pad_for_cuda_graph pads every rank to a common cg_batch_size and MTP tokens-per-seq is uniform), gated so the tight budget is only taken while the MoE-GEMM row count stays in the fast small-M trtllm-gen tactic region (https://nvbugspro.nvidia.com/bug/6247543); in eager (prefill or bypass) it falls back to the static max_num_tokens every rank computes identically. No per-layer host read. - Drop the now-dead batch_info_host plumbing for the DP-max slot: the slot-14 (max_dp_num_tokens) storage and update/get accessors in BatchInfo (_NUM_ELEMENTS 15->14), the pre-forward tp_allgather + update in the AD shim, and the batch_info_host injection into the MoE op in both the dict-based (sharding.py) and IR-based (sharding_ir.py) sharding paths, plus the op signatures in trtllm_moe.py / torch_moe.py. MTP + attention-DP correctness: - Keep the draft-EP revert under attention-DP in sharding (replicate the draft model's MoE rather than EP-sharding it) to avoid the shared-workspace corruption that hangs the all-to-all at concurrency. - Forward max_draft_len / max_total_draft_tokens to PyExecutor so the attention-DP dummy request is seeded with py_draft_tokens=[1]*max_total_draft_tokens instead of [], preventing it from classifying as decode and tripping the eagle wrapper's `assert num_decode == 0` under MTP + attention_dp. Mixed-mode cuda-graph bypass uses upstream's process-wide BypassCapturedGraphs() context manager (cuda_graph_state.in_bypass()), keeping all ranks consistent when one is in prefill. Note: the attention-DP request balancer is intentionally NOT included here; it showed no throughput gain in benchmarking and will be evaluated in a follow-up. Tests: - Add NVFP4 SuperV3-MTP attn-DP perf-sanity config + post-merge enrollment. - test_mtp / test_accuracy NVFP4 coverage resolved to upstream's parametrization. Signed-off-by: Eran Geva <19514940+MrGeva@users.noreply.github.com>
…mization Rebases the SuperV3-MTP attention-DP optimization onto current upstream/main (which now carries gk's MoE all-to-all stateful cache NVIDIA#13718/NVIDIA#13723 and gagam's SSM-replay PR). MoE all-to-all per-rank token budget (runtime_max_tokens_per_rank): - Replace the per-iteration cross-rank-max read (an int(batch_info_host[14] .item()) on a pinned-host tensor, fed by a per-forward tp_allgather) with a sync-free shape-based budget via _hybrid_runtime_max_tokens_per_rank: under cuda-graph capture/warm-up the budget is x.shape[0] (uniform across DP ranks because maybe_pad_for_cuda_graph pads every rank to a common cg_batch_size and MTP tokens-per-seq is uniform), gated so the tight budget is only taken while the MoE-GEMM row count stays in the fast small-M trtllm-gen tactic region (https://nvbugspro.nvidia.com/bug/6247543); in eager (prefill or bypass) it falls back to the static max_num_tokens every rank computes identically. No per-layer host read. - Drop the now-dead batch_info_host plumbing for the DP-max slot: the slot-14 (max_dp_num_tokens) storage and update/get accessors in BatchInfo (_NUM_ELEMENTS 15->14), the pre-forward tp_allgather + update in the AD shim, and the batch_info_host injection into the MoE op in both the dict-based (sharding.py) and IR-based (sharding_ir.py) sharding paths, plus the op signatures in trtllm_moe.py / torch_moe.py. MTP + attention-DP correctness: - Keep the draft-EP revert under attention-DP in sharding (replicate the draft model's MoE rather than EP-sharding it) to avoid the shared-workspace corruption that hangs the all-to-all at concurrency. - Forward max_draft_len / max_total_draft_tokens to PyExecutor so the attention-DP dummy request is seeded with py_draft_tokens=[1]*max_total_draft_tokens instead of [], preventing it from classifying as decode and tripping the eagle wrapper's `assert num_decode == 0` under MTP + attention_dp. Mixed-mode cuda-graph bypass uses upstream's process-wide BypassCapturedGraphs() context manager (cuda_graph_state.in_bypass()), keeping all ranks consistent when one is in prefill. Note: the attention-DP request balancer is intentionally NOT included here; it showed no throughput gain in benchmarking and will be evaluated in a follow-up. Tests: - Add NVFP4 SuperV3-MTP attn-DP perf-sanity config + post-merge enrollment. - test_mtp / test_accuracy NVFP4 coverage resolved to upstream's parametrization. Signed-off-by: Eran Geva <19514940+MrGeva@users.noreply.github.com>
…mization Rebases the SuperV3-MTP attention-DP optimization onto current upstream/main (which now carries gk's MoE all-to-all stateful cache NVIDIA#13718/NVIDIA#13723 and gagam's SSM-replay PR). MoE all-to-all per-rank token budget (runtime_max_tokens_per_rank): - Replace the per-iteration cross-rank-max read (an int(batch_info_host[14] .item()) on a pinned-host tensor, fed by a per-forward tp_allgather) with a sync-free shape-based budget via _hybrid_runtime_max_tokens_per_rank: under cuda-graph capture/warm-up the budget is x.shape[0] (uniform across DP ranks because maybe_pad_for_cuda_graph pads every rank to a common cg_batch_size and MTP tokens-per-seq is uniform), gated so the tight budget is only taken while the MoE-GEMM row count stays in the fast small-M trtllm-gen tactic region (https://nvbugspro.nvidia.com/bug/6247543); in eager (prefill or bypass) it falls back to the static max_num_tokens every rank computes identically. No per-layer host read. - Drop the now-dead batch_info_host plumbing for the DP-max slot: the slot-14 (max_dp_num_tokens) storage and update/get accessors in BatchInfo (_NUM_ELEMENTS 15->14), the pre-forward tp_allgather + update in the AD shim, and the batch_info_host injection into the MoE op in both the dict-based (sharding.py) and IR-based (sharding_ir.py) sharding paths, plus the op signatures in trtllm_moe.py / torch_moe.py. MTP + attention-DP correctness: - Keep the draft-EP revert under attention-DP in sharding (replicate the draft model's MoE rather than EP-sharding it) to avoid the shared-workspace corruption that hangs the all-to-all at concurrency. - Forward max_draft_len / max_total_draft_tokens to PyExecutor so the attention-DP dummy request is seeded with py_draft_tokens=[1]*max_total_draft_tokens instead of [], preventing it from classifying as decode and tripping the eagle wrapper's `assert num_decode == 0` under MTP + attention_dp. Mixed-mode cuda-graph bypass uses upstream's process-wide BypassCapturedGraphs() context manager (cuda_graph_state.in_bypass()), keeping all ranks consistent when one is in prefill. Note: the attention-DP request balancer is intentionally NOT included here; it showed no throughput gain in benchmarking and will be evaluated in a follow-up. Tests: - Add NVFP4 SuperV3-MTP attn-DP perf-sanity config + post-merge enrollment. - test_mtp / test_accuracy NVFP4 coverage resolved to upstream's parametrization. Signed-off-by: Eran Geva <19514940+MrGeva@users.noreply.github.com>
Summary
Closes #13718.
Closes #13360.
Implementation
_GlobalMoeA2ACacheintensorrt_llm/_torch/auto_deploy/custom_ops/fused_moe/trtllm_moe.pycachesMoeAlltoAllinstances and parsedDistConfigmappings, eliminating per-call Python ctor + JSON deserialization (mirrors_GlobalTrtllmPlannerintrtllm_attention.py).BatchInfoslot 13: pre-forwardtp_allgatherinADEnginewrites the cross-rankmax(total_num_tokens)to the slot; the MoE custom op reads it at capture/eager time. Replaces the staticmax_num_tokensover-padding with the per-iteration cross-rank max — matches base TRT-LLM'sruntime_max_tokens_per_rankfromfused_moe_cutlass.py:764.Files touched:
tensorrt_llm/_torch/auto_deploy/custom_ops/attention_interface.py—BatchInfo._NUM_ELEMENTS = 14, slot 13 helperstensorrt_llm/_torch/auto_deploy/shim/ad_executor.py— pre-forwardtp_allgatheroverridetensorrt_llm/_torch/auto_deploy/transform/library/sharding.py— threadbatch_info_hostgraph input into MoE op call sitestensorrt_llm/_torch/auto_deploy/custom_ops/fused_moe/trtllm_moe.py—_GlobalMoeA2ACache+ slot 13 read in dispatch pathtensorrt_llm/_torch/auto_deploy/custom_ops/fused_moe/torch_moe.py—batch_info_hostkwarg threading for sharding-time targetsWhy this is safe under CUDA-graph capture
The
int(batch_info_host[13].item())read is on a pinned-host CPU tensor — pure Python read, no GPU sync. Under graph capture the value is baked in at capture time, so each captured graph corresponds to thecg_batch_sizebucket it was warmed at. AD's existingmaybe_pad_for_cuda_graph(ad_executor.py) syncsbatch_sizeacross ranks viatp_allgatherand pads up tocg_batch_size— so for any decode replay path, all DP ranks have the sametotal_num_tokens, and the captured constant equals the runtime cross-rank max.For eager paths (prefill, mixed batches, fallback when sync gate fails), the
.item()re-runs Python and reads the just-written cross-rank max — also correct.Test plan
/bot run --extra-stage "DGX_H100-4_GPUs-AutoDeploy-1, DGX_B200-4_GPUs-AutoDeploy-1"— multi-GPU AutoDeploy stages exercise this pathpytest tests/integration/defs/accuracy/test_llm_api_autodeploy.py -k "attn_dp"(attention-DP variants)bench-sweepcomparing main vs this branch on Nemotron-Nano + attention-DP — expect dispatch padding to shrink frommax_num_tokens=2048toruntime_max ≈ batch_size * (1 + draft_len)Validation already done locally
tests/unittest/auto_deploy/multigpu/transformations/library/test_ep_sharding.py::test_ep_shard(4/4 PASS) on the cache-only stageexamples/auto_deploy/build_and_run_ad.py --yaml-extra _repro_logs/nano_attn_dp_smoke.yamlon Nemotron-Nano-30B-FP8 + attn-DP + 4×H100, 10/10 prompts, coherent generation, no NaN. With diagnostic instrumentation:enable_attention_dp=True, tp_size=4)tp_allgatherreturns proper 4-element list (e.g.,[53, 56, 56, 77]); all ranks compute and write the samemax=77slot13=77while theirlocal_num_tokensdiffer: 53/56/56/77)Summary by CodeRabbit
Release Notes
New Features
Performance