Skip to content

[TRTLLM-13579][feat] BREAKING: Support BCG in Prefill - #16609

Open
GuanhuaWang2001 wants to merge 24 commits into
NVIDIA:mainfrom
GuanhuaWang2001:feature/bcg
Open

[TRTLLM-13579][feat] BREAKING: Support BCG in Prefill#16609
GuanhuaWang2001 wants to merge 24 commits into
NVIDIA:mainfrom
GuanhuaWang2001:feature/bcg

Conversation

@GuanhuaWang2001

@GuanhuaWang2001 GuanhuaWang2001 commented Jul 20, 2026

Copy link
Copy Markdown

Summary

Adds breakable prefill CUDA graphs (BCG) support to the PyTorch backend by capturing decoder-body segments into CUDA-graph segments while executing dynamic Attention/GDN operations eagerly at explicit breakpoints. Introduces prefill-specific CUDA-graph configuration (DISABLED/PIECEWISE/BREAKABLE) and migrates legacy piecewise options into these new prefill fields (with deprecation warnings). Runtime routing uses per-request prefill gating so only supported prefill requests use BCG capture/replay; unsupported cases fall back to eager execution.

Integrates BreakableCUDAGraphRunner into ModelEngine for token-bucket capture/replay, including prefill padding feasibility calculation, capture warmup/capture/execute routing, and robust capture teardown. Attention/GDN/minimaxm3 custom ops are wrapped with BCG-aware execution via eager_on_graph and is_in_breakable_cuda_graph() to allow correct custom-op behavior inside breakable graph regions.

Also updates DeepSeek-V4 “DSv4 epilogue fusion” MLA plumbing to a simplified single-tensor custom-op schema and routes MLA custom-op call sites through BCG-wrapped variants when breakable CUDA-graph execution is active. Includes docs, API/export updates, and expanded unit/integration test coverage for the breakable capture lifecycle and config migration.

Dev Engineer Review

  • BCG implementation & routing correctness

    • Added breakable CUDA graph primitives: BreakableCUDAGraph, BreakableCUDAGraphCapture, eager_on_graph, and break_graph, including ContextVar-based capture state, stream capture segmentation, side-stream synchronization, and _copy_output writeback for structured outputs.
    • Added BreakableCUDAGraphRunner state machine (IDLE/WARMUP/CAPTURE/REPLAY) that captures only the decoder-body by temporarily patching layer_model.forward, then replays for requested num_tokens buckets with validated output copying.
    • Integrated BCG into ModelEngine via PrefillCudaGraphBackend, including:
      • capture warmup/capture/execute routing through _capture_prefill_cuda_graphs and _run_cuda_graph_warmup
      • token-bucket selection and padding feasibility computation in _get_padding_params (with TP-rank-uniform gating)
      • per-request routing using set/get_per_request_prefill_cuda_graph_flag(...), with eager fallback when graphs are missing, warming up, capture is in progress, or the per-request flag is disabled.
  • Correctness of custom-op behavior under breakable graphs

    • Attention: enabled inplace attn_custom_op_inplace within breakable regions by introducing maybe_bcg_attn_custom_op_inplace = eager_on_graph(...) and expanding the dispatch condition to include is_in_breakable_cuda_graph().
    • GDN (mamba): added breakable-wrapped gdn_custom_op_inplace selection under breakable mode (while preserving non-marlin constraints), plus refactored GDN state zeroing into a helper.
    • MiniMaxM3: expanded custom-op dispatch to use the BCG-wrapped inplace op when is_in_breakable_cuda_graph() is true.
    • MLA/DSv4 fusion: simplified custom-op schema to mutate only the final output tensor; updated routing to call BCG-wrapped custom-op variants when inside breakable CUDA-graph execution.
  • API/config consistency

    • Added PrefillCudaGraphBackend and new TorchLlmArgs fields:
      • prefill_cuda_graph_backend
      • prefill_capture_num_tokens
    • Implemented normalize_prefill_cuda_graph_config() migration:
      • deprecated legacy torch_compile_config.enable_piecewise_cuda_graph / torch_compile_config.capture_num_tokens → prefill fields (with warnings)
      • validates invalid combinations (notably BREAKABLE + non-None torch_compile_config, and encode_only conflicts)
      • ensures defaults for prefill_capture_num_tokens and PIECEWISE behavior.
    • Replaced per-request piecewise gating APIs with prefill gating APIs in tensorrt_llm/_torch/utils.py.
  • Performance/memory/execution boundaries

    • Introduced token-bucket based capture/replay to reduce end-to-end prefill latency while keeping dynamic Attention/GDN eager at breakpoints.
    • Added runner output copyback and weak-ref handling (make_weak_ref(..., preserve_unsupported=...)) to safely replay complex outputs and preserve unsupported objects where needed.
  • Config/docs updates

    • Updated feature docs to reflect new prefill-specific configuration names and added an experimental prefill_cuda_graph_backend: breakable example.
    • Updated gating logic in piecewise_optimizer.py to use per-request prefill flags.
  • CI / follow-ups

    • Objectives indicate an initial CI failure for commit f8fad38, followed by retriggers where downstream L0_MergeRequest_PR pipelines reported FAILURE; additional follow-up was requested. Given current test-list entry TIMEOUTs (below), CI stability and runtime performance investigation likely needs follow-up.

QA Engineer Review

Test-list / test-db changes (integration CI selection)

Modified:

  • tests/integration/test_lists/test-db/l0_b200.yml
    • Added: accuracy/test_llm_api_pytorch.py::TestQwen3_5_4B::test_bf16_breakable_prefill_cuda_graph
  • tests/integration/test_lists/test-db/l0_dgx_b200.yml
    • Added:
      • accuracy/test_llm_api_pytorch.py::TestDeepSeekV32::test_nvfp4_multi_gpus_breakable_cuda_graph[baseline] (TIMEOUT)
      • accuracy/test_llm_api_pytorch.py::TestDeepSeekV32::test_nvfp4_multi_gpus_breakable_cuda_graph[mtp3_fp8kv_chunked] (TIMEOUT)
      • accuracy/test_llm_api_pytorch.py::TestDeepSeekV4Flash::test_mixed_breakable_cuda_graph (TIMEOUT, ISOLATION)
      • accuracy/test_disaggregated_serving.py::TestDeepSeekV4Flash::test_prefill_breakable_cuda_graph (TIMEOUT, ISOLATION)

Verdict (test-list coverage): needs follow-up (entries currently show TIMEOUTs).

Test code changes (files outside test-db)

Integration tests

  • tests/integration/defs/accuracy/test_llm_api_pytorch.py
    • Added/updated:
      • TestQwen3_5_4B.test_bf16_breakable_prefill_cuda_graph
      • TestDeepSeekV32.test_nvfp4_multi_gpus_breakable_cuda_graph(...)
      • TestDeepSeekV4Flash.test_mixed_breakable_cuda_graph
    • Covered in test-db/:
      • l0_b200.yml (Qwen3.5-4B bf16 breakable prefill)
      • l0_dgx_b200.yml (DeepSeekV32 + DeepSeekV4Flash breakable cases; TIMEOUT observed)
  • tests/integration/defs/accuracy/test_disaggregated_serving.py
    • Added: TestDeepSeekV4Flash.test_prefill_breakable_cuda_graph
    • Covered in test-db/: l0_dgx_b200.yml (TIMEOUT observed)

Unit tests (CPU/GPU dependent; executed in unit CI lanes)

  • tests/unittest/_torch/executor/test_breakable_cuda_graph.py
    • Added extensive coverage for breakable capture/replay lifecycle; includes test_runner_warmup_capture_execute_and_shared_output
    • Covered in test-db/: not indicated; should run in unit CI (no test-db mapping provided)
  • tests/unittest/_torch/compilation/test_remove_copy_pass.py
    • Renamed/adjusted MLA-related assertion tests for new DSV4/MLA mutation schema
  • tests/unittest/_torch/modules/test_mla_registry.py
    • Added tests for DSv4 epilogue fusion behavior under breakable graphs and updated custom-op schemas
  • tests/unittest/llmapi/test_llm_args.py
    • Added tests for prefill_cuda_graph_backend / prefill_capture_num_tokens migration/validation and padding equivalence behavior
  • tests/unittest/_torch/attention/sparse/deepseek_v4/test_deepseek_v4_o_proj.py
    • Minor test invocation adjustment to pass enable_dsv4_epilogue_fusion=False

Verdict (test code coverage): insufficient / needs follow-up (because the primary new integration test-db entries are timing out in l0_dgx_b200.yml, and prior CI failures were reported in the objectives).

Summary

Adds breakable prefill CUDA graphs (BCG) to the PyTorch backend. BCG captures the decoder body as segmented CUDA graphs while executing dynamic Attention/GDN operations eagerly at graph breakpoints.

Design

  • Adds one BreakableCUDAGraphRunner integrated directly into ModelEngine.
  • Warmup executes the complete eager forward; capture records the model body; replay temporarily replaces the body forward while preserving the outer model, logits processor, and postprocessing.
  • PCG and BCG share prefill buckets, padding, dummy requests, and ADP token-shape synchronization.
  • Attention and GDN use request-local metadata at BCG breakpoints.
  • Unsupported LoRA, multimodal, context-logits, and speculative-decoding requests fall back to eager execution.

Validation

Tested with a Release SM100 build on B200 GPUs:

  • Qwen3.5-4B BF16: eager/BCG token equality, exact buckets, upward padding, mixed batches, repeated prompts, Attention and GDN state.
  • Qwen3.5-397B-A17B NVFP4: TP4/EP4 and TP4/EP4/Attention-DP.
  • BCG primitives and configuration tests: 20 passed.

All latency values are end-to-end LLM.generate() P50 in milliseconds with one generated token, overlap scheduling disabled, and KV-cache block reuse disabled.

Qwen3.5-4B BF16, 1×B200

Parameters:

common_args = {
    "model": "/path/to/Qwen3.5-4B",
    "backend": "pytorch",
    "max_batch_size": 1,
    "max_seq_len": 528,
    "max_num_tokens": 512,
    "disable_overlap_scheduler": True,
    "kv_cache_config": KvCacheConfig(
        free_gpu_memory_fraction=0.8,
        enable_block_reuse=False,
    ),
}

capture_num_tokens = [128, 256, 512]
sampling_params = SamplingParams(max_tokens=1, temperature=0.0)
# 3 warmups and 20 measured iterations.

Backend overrides:

# Eager
prefill_cuda_graph_backend = "disabled"

# PCG
prefill_cuda_graph_backend = "piecewise"
prefill_capture_num_tokens = capture_num_tokens
torch_compile_config = TorchCompileConfig(max_num_streams=3)

# BCG
prefill_cuda_graph_backend = "breakable"
prefill_capture_num_tokens = capture_num_tokens
Prompt tokens Eager PCG, streams=3 BCG
64 37.831 28.784 20.877
128 37.444 28.881 20.594
129 37.632 29.140 20.898
256 37.161 28.660 20.825
257 37.142 27.284 21.788
384 37.438 27.045 21.822
512 37.233 27.015 21.831

Qwen3.5-397B-A17B NVFP4, 4×B200

Common parameters:

common_args = {
    "model": "/path/to/Qwen3.5-397B-A17B-NVFP4",
    "backend": "pytorch",
    "tensor_parallel_size": 4,
    "moe_expert_parallel_size": 4,
    "moe_config": MoeConfig(backend="TRTLLM"),
    "max_seq_len": 1024,
    "max_num_tokens": 512,
    "disable_overlap_scheduler": True,
    "batch_wait_timeout_ms": 10,
}

capture_num_tokens = [128, 256, 384, 512]
sampling_params = SamplingParams(max_tokens=1, temperature=0.0)

max_batch_size = 4
total_prompt_tokens = [128, 256, 384, 512]
kv_cache_config = KvCacheConfig(
free_gpu_memory_fraction=0.85,
enable_block_reuse=False,
)
cuda_graph_config = CudaGraphConfig(max_batch_size=4, enable_padding=True)

Attention-DP:

enable_attention_dp = True
max_batch_size = 16
total_prompt_tokens = [512, 1024, 1536, 2048]
kv_cache_config = KvCacheConfig(
free_gpu_memory_fraction=0.5,
enable_block_reuse=False,
)
cuda_graph_config = CudaGraphConfig(max_batch_size=16, enable_padding=True)

Mode Total prompt tokens Eager PCG, streams=3 BCG
TP4/EP4 128 124.389 93.631 41.762
TP4/EP4 256 125.189 95.654 43.268
TP4/EP4 384 125.108 96.560 44.634
TP4/EP4 512 130.283 90.857 45.202
TP4/EP4/ADP 512 123.947 79.385 50.991
TP4/EP4/ADP 1024 124.870 80.664 58.522
TP4/EP4/ADP 1536 125.105 83.351 67.629
TP4/EP4/ADP 2048 124.353 86.945 70.778


if self.prefill_cuda_graph_backend == PrefillCudaGraphBackend.PIECEWISE:
if self.torch_compile_config is None:
self.torch_compile_config = TorchCompileConfig()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enable_piecewise_cuda_graph is default off. And capture_num_tokens should be setup.

Besides, we would need to set max_num_streams to maybe 3 to ensure the best performance.

@pytest.mark.threadleak(enabled=False)
def test_bf16_breakable_prefill_cuda_graph(self):
model_path = f"{llm_models_root()}/Qwen3.5-4B"
prompts = [

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe directly test with GSM8K and MMLU.

def _weak_ref_if_tensor(value: Any) -> Any:
if torch.is_tensor(value):
return make_weak_ref(value)
if isinstance(value, tuple):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think make_weak_ref already handle the tuple/list/...

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import?

return hidden_states

self.layer_model.forward = capture_forward
self.logits_processor.forward = passthrough_forward

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering why we need to handle logits_processor differently. That might be a blocker when enabling spec dec support.

Comment thread tensorrt_llm/_torch/modules/mla.py Outdated
o_lora.transpose(0, 1),
)
return self.o_b_proj(o_lora.flatten(1))
if attn_out_latent.shape[1:] == (self.n_local_groups, self.o_lora_rank):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Directly pass in enable_dsv4_epilogue_fusion is more clear.

Comment thread tensorrt_llm/_torch/modules/mla.py Outdated
raise RuntimeError(
"DSv4 epilogue fusion requires a context-only or generation-only batch."
)
enable_dsv4_epilogue_fusion = output.ndim == 3

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, explicitly pass in enable_dsv4_epilogue_fusion

return source


def eager_on_graph(enable: bool) -> Callable[[Callable], Callable]:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the meaning of eager_on_graph(False) comparing without using the decorator?

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This PR adds prefill CUDA graph backends, segmented breakable capture and replay, PyTorch engine integration, DeepSeek-V4 MLA epilogue-fusion changes, breakable custom-op dispatch, and related unit, integration, and API-stability coverage.

Changes

Prefill configuration and compatibility

Layer / File(s) Summary
Prefill backend configuration and compatibility
tensorrt_llm/llmapi/..., tensorrt_llm/_torch/utils.py, docs/source/features/..., tensorrt_llm/usage/..., tests/unittest/llmapi/..., tests/unittest/api_stability/...
Adds prefill backend selection and capture buckets, migrates deprecated piecewise settings, updates per-request gating and exports, and documents the new configuration.

Breakable CUDA graph runtime

Layer / File(s) Summary
Capture, eager breaks, and replay runner
tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph/..., tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph_runner.py, tests/unittest/_torch/executor/test_breakable_cuda_graph.py
Adds segmented CUDA graph capture, eager breaks, stream synchronization, output writeback, runner lifecycle management, CUDA helpers, and CUDA tests.

Prefill engine integration

Layer / File(s) Summary
Prefill capture and execution flow
tensorrt_llm/_torch/pyexecutor/model_engine.py, tests/integration/defs/accuracy/..., tests/integration/test_lists/...
Adds backend-specific warmup and capture, token filtering, rank-aware padding, breakable replay, eager fallback, cleanup, and integration coverage.

Custom operations and MLA epilogue fusion

Layer / File(s) Summary
Breakable custom-op dispatch and DeepSeek-V4 outputs
tensorrt_llm/_torch/modules/..., tensorrt_llm/_torch/models/..., tests/unittest/_torch/modules/test_mla_registry.py, tests/unittest/_torch/attention/...
Routes attention, Mamba, MiniMax, and MLA operations through breakable wrappers and changes DeepSeek-V4 fusion to tensor-only outputs with centralized O-LoRA BMM execution.

Functionalization mutation validation

Layer / File(s) Summary
FX mutation regression tests
tests/unittest/_torch/compilation/test_remove_copy_pass.py
Updates MLA mutation coverage to verify preservation of the final output mutation.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TorchLlmArgs
  participant PyTorchModelEngine
  participant BreakableCUDAGraphRunner
  participant ModelBody
  TorchLlmArgs->>PyTorchModelEngine: configure prefill backend and token buckets
  PyTorchModelEngine->>BreakableCUDAGraphRunner: warm up and capture buckets
  BreakableCUDAGraphRunner->>ModelBody: capture segmented prefill execution
  PyTorchModelEngine->>BreakableCUDAGraphRunner: replay matching token bucket
  BreakableCUDAGraphRunner->>ModelBody: execute captured segments and eager breaks
Loading

Suggested reviewers: qijune

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the repo template and clearly summarizes the main change: adding breakable prefill BCG support.
Description check ✅ Passed The description includes Summary, Design, and Validation details that explain the change and test coverage, with only the checklist section omitted.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/source/features/torch_compile_and_piecewise_cuda_graph.md (1)

9-9: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Stale TOC anchor after the heading rename.

Line 1 is now "Torch Compile & Prefill CUDA Graph", so the anchor #torch-compile--piecewise-cuda-graph no longer resolves.

📝 Proposed fix
-- [Torch Compile & Piecewise CUDA Graph](`#torch-compile--piecewise-cuda-graph`)
+- [Torch Compile & Prefill CUDA Graph](`#torch-compile--prefill-cuda-graph`)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/source/features/torch_compile_and_piecewise_cuda_graph.md` at line 9,
Update the table-of-contents link in the “Torch Compile & Prefill CUDA Graph”
documentation to use the heading’s current generated anchor, replacing the stale
piecewise-cuda-graph fragment while preserving the existing link target.
🧹 Nitpick comments (9)
tests/unittest/_torch/compilation/test_remove_copy_pass.py (1)

25-87: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover the new malformed optional-output path.

Neither test sets a write argument’s _<arg>_base_index to None and then requests its getitem output, so the new assertion in remove_copy_for_mutates_args() is untested. Add a focused pytest.raises(AssertionError, match="graph is malformed") case.

Test coverage summary

  • Added: test_remove_copy_for_mutates_args_auto_functionalized_v2; test_remove_copy_for_mla_restores_final_output_mutation.
  • Test-list registration: no tests/integration/test_lists/ file was supplied; not assessable from this review context.
  • Verdict: insufficient — the newly added None-base invariant lacks coverage.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unittest/_torch/compilation/test_remove_copy_pass.py` around lines 25 -
87, Add a focused pytest.raises(AssertionError, match="graph is malformed") test
alongside test_remove_copy_for_mutates_args_auto_functionalized_v2 that
constructs an auto_functionalized_v2 graph with a write argument’s
_<arg>_base_index set to None while requesting its getitem output, then calls
remove_copy_pass.remove_copy_for_mutates_args(graph).

Source: Path instructions

tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph/cuda_utils.py (1)

17-25: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Type the CUDA result helper contract.

check_cuda_errors(result) has no parameter or return annotation despite being the central adapter for cuda-python result tuples. Add overloads or a generic tuple contract so callers cannot accidentally pass an incompatible result shape.

As per coding guidelines, “Annotate every function” and avoid imprecise types.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph/cuda_utils.py` around
lines 17 - 25, Annotate the check_cuda_errors function with precise parameter
and return types matching cuda-python result tuples, using overloads or a
generic tuple contract to represent one-element, two-element, and multi-element
results. Ensure the annotations reject incompatible result shapes while
preserving the existing None, single-value, and tuple return behavior.

Source: Coding guidelines

tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph/breakable_cuda_graph.py (1)

146-185: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Preserve decorated callable types.

eager_on_graph() exposes bare Callable, while wrapper, the weak-ref helper, and replay_fn lose argument and return types through Any. Use ParamSpec and TypeVar so decorated custom operations retain their callable contract.

As per coding guidelines, “Annotate every function” and “use precise Callable types.” Based on learnings, this repository supports Python 3.10+ typing features.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph/breakable_cuda_graph.py`
around lines 146 - 185, Update eager_on_graph and its nested functions to
preserve callable signatures using ParamSpec and TypeVar: type the decorator as
accepting and returning Callable[P, R], annotate wrapper with P/R, and annotate
replay_fn and make_weak_ref_with_str_none with precise argument and return types
instead of bare Callable or Any. Preserve the existing runtime behavior while
applying Python 3.10+ typing features throughout the added functions.

Sources: Coding guidelines, Learnings

tensorrt_llm/_torch/modules/attention.py (1)

932-944: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Split the compile and BCG custom-op paths tensorrt_llm/_torch/modules/attention.py#L932-L944, tensorrt_llm/_torch/models/modeling_minimaxm3.py#L1102-L1113, and tensorrt_llm/_torch/modules/mla.py#L3069-L3079 all route through the eager_on_graph(True) wrapper for both torch.compile and BCG. Follow tensorrt_llm/_torch/modules/mamba/gdn_mixer.py#L996-L1006 and use the raw custom op on the compile path, reserving the wrapper for the breakable-CUDA-graph case.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_torch/modules/attention.py` around lines 932 - 944, Split the
custom-op handling for torch.compile and breakable CUDA graph paths, using the
raw custom op during compilation and reserving the eager_on_graph(True) wrapper
for BCG execution. Apply this consistently at
tensorrt_llm/_torch/modules/attention.py:932-944,
tensorrt_llm/_torch/models/modeling_minimaxm3.py:1102-1113, and
tensorrt_llm/_torch/modules/mla.py:3069-3079, following the existing pattern in
gdn_mixer.py.
tensorrt_llm/_torch/pyexecutor/model_engine.py (2)

6194-6208: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Capture path returns early, skipping post-forward hooks.

return breakable_runner.capture_model_body(forward_step) bypasses self.forward_pass_callable() and _execute_logit_post_processors(...) that every other branch runs. That is presumably intentional for warmup-only capture, but it is not obvious from the code — a short comment stating that capture never produces user-visible logits would prevent a future regression here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_torch/pyexecutor/model_engine.py` around lines 6194 - 6208, Add
a concise comment immediately before the early return from
breakable_runner.capture_model_body(forward_step) explaining that the capture
path is warmup-only and produces no user-visible logits, so it intentionally
bypasses self.forward_pass_callable() and _execute_logit_post_processors(...).

775-784: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Runner construction rejects wrapped models with an opaque message.

drafting_loop_wrapper replaces self.model with a BaseDraftingLoopWrapper, so isinstance(decoder_model, DecoderModelForCausalLM) fails and the user sees "requires a decoder model body" rather than "speculative decoding is unsupported by the breakable prefill backend". Consider naming the unsupported configuration in the error.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_torch/pyexecutor/model_engine.py` around lines 775 - 784,
Update the validation in the breakable prefill runner initialization around
decoder_model to recognize models wrapped by drafting_loop_wrapper and reject
that unsupported speculative-decoding configuration with an explicit error
message stating that speculative decoding is unsupported by the breakable
prefill backend.
docs/source/features/torch_compile_and_piecewise_cuda_graph.md (1)

44-66: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Clarify the breakable support matrix sentence.

"supports BF16 Qwen3.5 on one GPU for context-only, tensor/pipeline parallelism and mixed context/decode batches" reads self-contradictory (one GPU vs TP/PP). Consider splitting into an explicit supported/unsupported list.

Also applies to: 80-82

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/source/features/torch_compile_and_piecewise_cuda_graph.md` around lines
44 - 66, Clarify the breakable backend support statement by separating supported
and unsupported configurations, avoiding the contradiction between “one GPU” and
tensor/pipeline parallelism. Explicitly state the supported BF16 Qwen3.5
context-only and mixed context/decode cases, identify the supported parallelism
scope, and list unsupported configurations separately; update the corresponding
repeated statement as well.
tests/unittest/llmapi/test_llm_args.py (1)

1645-1685: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Padding tests rely on a hand-built PyTorchModelEngine via object.__new__.

This works today but silently breaks whenever _get_padding_params starts reading another attribute. Consider extracting the padding decision into a small free function (or a @staticmethod taking the bucket list/backend) so the tests can call it without constructing a partially-initialized engine.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unittest/llmapi/test_llm_args.py` around lines 1645 - 1685, Extract the
padding decision logic used by PyTorchModelEngine._get_padding_params into a
standalone helper or static method that accepts the padding bucket list and
backend explicitly. Update _get_padding_params and the tests
test_piecewise_and_breakable_use_identical_padding and
test_attention_dp_prefill_graph_uses_all_rank_decision to use this helper,
removing reliance on object.__new__(PyTorchModelEngine) for padding-only
behavior.
tests/integration/defs/accuracy/test_llm_api_pytorch.py (1)

3975-4084: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Trim the benchmark machinery from this correctness test.

The only assertions are the three determinism/equality checks at the end, yet the test builds two 8-GPU engines, runs 12 generation passes, and computes latency/throughput medians and "p90". statistics.quantiles(latencies, n=10, method="inclusive")[8] over five samples is not a meaningful p90, and the JSON dump to TRTLLM_DSV4_BCG_AB_RESULT_PATH is ad-hoc reporting rather than test output. Dropping the timing/stats/JSON block and reducing the round count would cut CI cost substantially without weakening the assertions; keep the perf comparison in a dedicated benchmark if it is still needed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/integration/defs/accuracy/test_llm_api_pytorch.py` around lines 3975 -
4084, Simplify run_variant and the surrounding result/reporting flow to make
this a correctness-only test: remove timing, throughput, statistics, perf
fields, console/result-file JSON reporting, and retain only generated token IDs
for determinism and cross-variant equality checks. Reduce the repeated
generation rounds to the minimum needed to validate repeatability, while
preserving disabled_repeatable, fusion_repeatable, and token_ids_match
assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph_runner.py`:
- Around line 106-111: Update the exception cleanup in the capture flow to clear
`_shared_output` whenever `created_memory_pool` is true and the newly created
pool is discarded because `self._graphs` is empty. Keep the existing graph reset
and pool cleanup behavior unchanged, ensuring a later `capture()` allocates a
fresh shared output.

In `@tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph/breakable_cuda_graph.py`:
- Around line 248-256: Make BreakableCUDAGraphCapture.__enter__ transactional:
wrap stream/context setup, ContextVar token installation, and _begin_new_segment
(which invokes capture_begin) in an except BaseException cleanup path. On
failure, undo every resource acquired so far—including resetting ContextVar
tokens, exiting the stream context, and removing the _install_wait_stream_hook
monkeypatch—then re-raise the original exception; keep normal successful entry
behavior unchanged.

In `@tensorrt_llm/_torch/pyexecutor/model_engine.py`:
- Around line 1997-2012: Guard the prefill capture block around
breakable_cuda_graph_runner.capture and the torch.compile warmup loop with
_assert_all_tp_ranks_have_warmup_batch(...). Invoke the assertion before
rank-local capture decisions so all TP ranks consistently skip or perform
capture when batch is unavailable, preventing missing BCG entries and replay
KeyErrors.

In `@tensorrt_llm/_torch/utils.py`:
- Around line 383-390: Update the stale flag call in
_apply_steady_gen_fast_prepare to use
set_per_request_prefill_cuda_graph_flag(...) instead of
set_per_request_piecewise_cuda_graph_flag(...). Preserve the existing argument
and fast-path behavior, ensuring the called setter matches the imported symbol
and avoids the NameError.

In `@tensorrt_llm/llmapi/llm_args.py`:
- Around line 5212-5226: Update the legacy bucket handling in the TorchLlmArgs
initialization flow to read capture_num_tokens only when that field was
explicitly set by the user, rather than when
TorchCompileConfig.set_default_capture_num_tokens auto-populated it. Preserve
the conflict validation for explicitly provided legacy buckets and the migration
warning/assignment for non-explicit prefill_capture_num_tokens.

In `@tests/integration/defs/accuracy/test_llm_api_pytorch.py`:
- Around line 6306-6342: Add the new Qwen test to the appropriate single-GPU
test-db list, and register the DeepSeekV4Flash epilogue-fusion A/B test in the
corresponding multi-GPU or QA list. Use the exact pytest node for
TestQwen3_5_4B::test_bf16_breakable_prefill_cuda_graph and the matching node for
the DeepSeekV4Flash test; update the relevant files under
tests/integration/test_lists/test-db/ or tests/integration/test_lists/qa/.

In `@tests/unittest/_torch/executor/test_breakable_cuda_graph.py`:
- Around line 5-6: Remove the unused gc and weakref imports from
test_breakable_cuda_graph.py, leaving the remaining imports and test behavior
unchanged.

In `@tests/unittest/_torch/modules/test_mla_registry.py`:
- Around line 87-112: Update
test_dsv4_epilogue_fusion_returns_only_final_output_inside_breakable_graph so it
does not patch is_in_breakable_cuda_graph, since create_mla_outputs_impl does
not consult it. Remove the unused context patch and rename the test to describe
only the behavior it actually verifies, or otherwise add a meaningful comparison
that distinguishes breakable and non-breakable contexts.

In `@tests/unittest/llmapi/test_llm_args.py`:
- Around line 1632-1643: Update the remaining later test cases in
test_prefill_filter_sorts_dedupes_and_drops_nonpositive and related tests to
import and call _filter_prefill_capture_num_tokens instead of
_filter_piecewise_capture_num_tokens. Use the defined model_engine symbol
consistently and do not add a compatibility alias.

---

Outside diff comments:
In `@docs/source/features/torch_compile_and_piecewise_cuda_graph.md`:
- Line 9: Update the table-of-contents link in the “Torch Compile & Prefill CUDA
Graph” documentation to use the heading’s current generated anchor, replacing
the stale piecewise-cuda-graph fragment while preserving the existing link
target.

---

Nitpick comments:
In `@docs/source/features/torch_compile_and_piecewise_cuda_graph.md`:
- Around line 44-66: Clarify the breakable backend support statement by
separating supported and unsupported configurations, avoiding the contradiction
between “one GPU” and tensor/pipeline parallelism. Explicitly state the
supported BF16 Qwen3.5 context-only and mixed context/decode cases, identify the
supported parallelism scope, and list unsupported configurations separately;
update the corresponding repeated statement as well.

In `@tensorrt_llm/_torch/modules/attention.py`:
- Around line 932-944: Split the custom-op handling for torch.compile and
breakable CUDA graph paths, using the raw custom op during compilation and
reserving the eager_on_graph(True) wrapper for BCG execution. Apply this
consistently at tensorrt_llm/_torch/modules/attention.py:932-944,
tensorrt_llm/_torch/models/modeling_minimaxm3.py:1102-1113, and
tensorrt_llm/_torch/modules/mla.py:3069-3079, following the existing pattern in
gdn_mixer.py.

In `@tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph/breakable_cuda_graph.py`:
- Around line 146-185: Update eager_on_graph and its nested functions to
preserve callable signatures using ParamSpec and TypeVar: type the decorator as
accepting and returning Callable[P, R], annotate wrapper with P/R, and annotate
replay_fn and make_weak_ref_with_str_none with precise argument and return types
instead of bare Callable or Any. Preserve the existing runtime behavior while
applying Python 3.10+ typing features throughout the added functions.

In `@tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph/cuda_utils.py`:
- Around line 17-25: Annotate the check_cuda_errors function with precise
parameter and return types matching cuda-python result tuples, using overloads
or a generic tuple contract to represent one-element, two-element, and
multi-element results. Ensure the annotations reject incompatible result shapes
while preserving the existing None, single-value, and tuple return behavior.

In `@tensorrt_llm/_torch/pyexecutor/model_engine.py`:
- Around line 6194-6208: Add a concise comment immediately before the early
return from breakable_runner.capture_model_body(forward_step) explaining that
the capture path is warmup-only and produces no user-visible logits, so it
intentionally bypasses self.forward_pass_callable() and
_execute_logit_post_processors(...).
- Around line 775-784: Update the validation in the breakable prefill runner
initialization around decoder_model to recognize models wrapped by
drafting_loop_wrapper and reject that unsupported speculative-decoding
configuration with an explicit error message stating that speculative decoding
is unsupported by the breakable prefill backend.

In `@tests/integration/defs/accuracy/test_llm_api_pytorch.py`:
- Around line 3975-4084: Simplify run_variant and the surrounding
result/reporting flow to make this a correctness-only test: remove timing,
throughput, statistics, perf fields, console/result-file JSON reporting, and
retain only generated token IDs for determinism and cross-variant equality
checks. Reduce the repeated generation rounds to the minimum needed to validate
repeatability, while preserving disabled_repeatable, fusion_repeatable, and
token_ids_match assertions.

In `@tests/unittest/_torch/compilation/test_remove_copy_pass.py`:
- Around line 25-87: Add a focused pytest.raises(AssertionError, match="graph is
malformed") test alongside
test_remove_copy_for_mutates_args_auto_functionalized_v2 that constructs an
auto_functionalized_v2 graph with a write argument’s _<arg>_base_index set to
None while requesting its getitem output, then calls
remove_copy_pass.remove_copy_for_mutates_args(graph).

In `@tests/unittest/llmapi/test_llm_args.py`:
- Around line 1645-1685: Extract the padding decision logic used by
PyTorchModelEngine._get_padding_params into a standalone helper or static method
that accepts the padding bucket list and backend explicitly. Update
_get_padding_params and the tests
test_piecewise_and_breakable_use_identical_padding and
test_attention_dp_prefill_graph_uses_all_rank_decision to use this helper,
removing reliance on object.__new__(PyTorchModelEngine) for padding-only
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: 93727c2d-fa02-4e5c-bb81-bebfd79a85ef

📥 Commits

Reviewing files that changed from the base of the PR and between 09e5d0c and f49b42d.

📒 Files selected for processing (25)
  • docs/source/features/torch_compile_and_piecewise_cuda_graph.md
  • tensorrt_llm/_torch/compilation/piecewise_optimizer.py
  • tensorrt_llm/_torch/compilation/remove_copy_pass.py
  • tensorrt_llm/_torch/models/modeling_minimaxm3.py
  • tensorrt_llm/_torch/modules/attention.py
  • tensorrt_llm/_torch/modules/mamba/gdn_mixer.py
  • tensorrt_llm/_torch/modules/mla.py
  • tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph/__init__.py
  • tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph/breakable_cuda_graph.py
  • tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph/context.py
  • tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph/cuda_utils.py
  • tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph_runner.py
  • tensorrt_llm/_torch/pyexecutor/model_engine.py
  • tensorrt_llm/_torch/utils.py
  • tensorrt_llm/llmapi/__init__.py
  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/usage/llm_args_golden_manifest.json
  • tests/integration/defs/accuracy/test_llm_api_pytorch.py
  • tests/integration/test_lists/waives.txt
  • tests/unittest/_torch/compilation/test_remove_copy_pass.py
  • tests/unittest/_torch/executor/test_breakable_cuda_graph.py
  • tests/unittest/_torch/modules/test_mla_registry.py
  • tests/unittest/api_stability/api_stability_core.py
  • tests/unittest/api_stability/references/llm.yaml
  • tests/unittest/llmapi/test_llm_args.py
💤 Files with no reviewable changes (1)
  • tests/integration/test_lists/waives.txt

Comment on lines +106 to +111
except Exception:
if graph is not None:
graph.reset()
if created_memory_pool and not self._graphs:
self._memory_pool = None
raise

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.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Reset _shared_output when the freshly created pool is discarded.

On a failed first capture the pool handle is dropped but _shared_output still references a tensor allocated inside that (now discarded) pool. A later capture() would then route bucket outputs into that stale buffer instead of allocating a new shared output.

🛠️ Proposed fix
             if created_memory_pool and not self._graphs:
                 self._memory_pool = None
+                self._shared_output = None
             raise
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
except Exception:
if graph is not None:
graph.reset()
if created_memory_pool and not self._graphs:
self._memory_pool = None
raise
except Exception:
if graph is not None:
graph.reset()
if created_memory_pool and not self._graphs:
self._memory_pool = None
self._shared_output = None
raise
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph_runner.py` around lines
106 - 111, Update the exception cleanup in the capture flow to clear
`_shared_output` whenever `created_memory_pool` is true and the newly created
pool is discarded because `self._graphs` is empty. Keep the existing graph reset
and pool cleanup behavior unchanged, ensuring a later `capture()` allocates a
fresh shared output.

Comment on lines +248 to +256
def __enter__(self) -> "BreakableCUDAGraphCapture":
_install_wait_stream_hook()
if self._stream is not None:
self._stream_context = torch.cuda.stream(self._stream)
self._stream_context.__enter__()
self._capture_token = _current_capture.set(self)
self._stream_token = _current_stream.set(self._stream or torch.cuda.current_stream())
self._forked_token = _forked_streams.set(set())
self._begin_new_segment()

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Make capture entry transactional.

If stream setup or capture_begin() on Line 274 raises, __exit__() is never called. The global wait_stream monkeypatch, ContextVar tokens, and possibly the stream context remain installed, corrupting later captures. Clean up each successfully acquired resource in an except BaseException path before re-raising.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_torch/pyexecutor/breakable_cuda_graph/breakable_cuda_graph.py`
around lines 248 - 256, Make BreakableCUDAGraphCapture.__enter__ transactional:
wrap stream/context setup, ContextVar token installation, and _begin_new_segment
(which invokes capture_begin) in an except BaseException cleanup path. On
failure, undo every resource acquired so far—including resetting ContextVar
tokens, exiting the stream context, and removing the _install_wait_stream_hook
monkeypatch—then re-raise the original exception; keep normal successful entry
behavior unchanged.

Comment thread tensorrt_llm/_torch/pyexecutor/model_engine.py
Comment thread tensorrt_llm/_torch/utils.py
Comment thread tensorrt_llm/llmapi/llm_args.py
Comment thread tests/integration/defs/accuracy/test_llm_api_pytorch.py
Comment thread tests/unittest/_torch/executor/test_breakable_cuda_graph.py Outdated
Comment on lines +87 to +112
def test_dsv4_epilogue_fusion_returns_only_final_output_inside_breakable_graph() -> None:
metadata = SimpleNamespace(num_contexts=1, num_generations=1, num_tokens=5)
mla_layer = Mock(spec=MLA)
mla_layer._should_use_dsv4_epilogue_fusion.return_value = True
mla_layer.create_output.return_value = torch.empty(8, 4, 2)
hidden_states = torch.empty(8, 8)

with (
patch(
"tensorrt_llm._torch.modules.mla._extract_mla_extra_attrs",
return_value=(metadata, mla_layer),
),
patch(
"tensorrt_llm._torch.modules.mla.is_in_breakable_cuda_graph",
return_value=True,
),
):
outputs = create_mla_outputs_impl(hidden_states, "0")

assert outputs == [mla_layer.create_output.return_value]
mla_layer.create_output.assert_called_once_with(
hidden_states,
1,
enable_dsv4_epilogue_fusion=True,
)
mla_layer._create_dsv4_epilogue_buffers.assert_not_called()

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

The is_in_breakable_cuda_graph patch has no effect on create_mla_outputs_impl.

create_mla_outputs_impl (mla.py lines 137-148) only calls _extract_mla_extra_attrs, _should_use_dsv4_epilogue_fusion, and create_output; it never consults is_in_breakable_cuda_graph. The test therefore asserts the same thing inside and outside a breakable region, so the "inside_breakable_graph" guarantee in the name is not actually exercised. Either drop the patch (and rename) or add an assertion that distinguishes the two contexts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unittest/_torch/modules/test_mla_registry.py` around lines 87 - 112,
Update
test_dsv4_epilogue_fusion_returns_only_final_output_inside_breakable_graph so it
does not patch is_in_breakable_cuda_graph, since create_mla_outputs_impl does
not consult it. Remove the unused context patch and rename the test to describe
only the behavior it actually verifies, or otherwise add a meaningful comparison
that distinguishes breakable and non-breakable contexts.

Comment thread tests/unittest/llmapi/test_llm_args.py
Signed-off-by: GuanhuaWang2001 <300454435+GuanhuaWang2001@users.noreply.github.com>
Signed-off-by: GuanhuaWang2001 <300454435+GuanhuaWang2001@users.noreply.github.com>
Signed-off-by: GuanhuaWang2001 <300454435+GuanhuaWang2001@users.noreply.github.com>
Signed-off-by: GuanhuaWang2001 <300454435+GuanhuaWang2001@users.noreply.github.com>
Signed-off-by: GuanhuaWang2001 <300454435+GuanhuaWang2001@users.noreply.github.com>
Signed-off-by: GuanhuaWang2001 <300454435+GuanhuaWang2001@users.noreply.github.com>
@GuanhuaWang2001

Copy link
Copy Markdown
Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65013 [ run ] triggered by Bot. Commit: a656945 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65013 [ run ] completed with state SUCCESS. Commit: a656945
/LLM/main/L0_MergeRequest_PR pipeline #52823 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

Signed-off-by: GuanhuaWang2001 <300454435+GuanhuaWang2001@users.noreply.github.com>
@GuanhuaWang2001

Copy link
Copy Markdown
Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65082 [ run ] triggered by Bot. Commit: efa156a Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65082 [ run ] completed with state SUCCESS. Commit: efa156a
/LLM/main/L0_MergeRequest_PR pipeline #52886 completed with status: 'UNSTABLE'

CI Report

⚠️ Multi-GPU Label Required:
Multi-GPU tests require the ci: full pre-merge approved label on this PR. Ask a member of NVIDIA/trt-llm-ci-approvers to add the label, then re-trigger CI with the same bot command (no rebase needed).

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

Link to invocation

@GuanhuaWang2001

Copy link
Copy Markdown
Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65182 [ run ] triggered by Bot. Commit: efa156a Link to invocation

Signed-off-by: GaunhuaWang-nv <300454435+GuanhuaWang2001@users.noreply.github.com>
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65182 [ run ] completed with state FAILURE. Commit: efa156a
/LLM/main/L0_MergeRequest_PR pipeline #52974 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

decoder_model = (self.model if isinstance(
self.model, DecoderModelForCausalLM) else getattr(
self.model, "llm", None))
if not isinstance(decoder_model, DecoderModelForCausalLM):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The advertised speculative-decoding support still fails for chain-drafter configurations. py_executor_creator.py:607-648 wraps the draft model in LinearDraftingLoopWrapper or StaticTreeDraftingLoopWrapper and copies these BREAKABLE args into the draft engine, but those wrappers expose .draft_model, not .llm; this branch therefore raises during engine construction. Either disable BCG for the draft engine or unwrap .draft_model here, and add a chain-drafter construction test.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This affects the deprecated two-model/chain-drafter path. MTP uses the one-model and does not instantiate these wrappers. Deepseek V3 / V4 with mtp can run safety.


max_num_streams: PositiveInt = Field(
default=1,
default=3,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
default=3,
default=1,

This default also drives compile-only TorchCompileConfig() with prefill_cuda_graph_backend=disabled; Backend.__call__ enables multi-stream scheduling whenever max_num_streams > 1, so this silently changes existing compile-only execution. Keep the public default at 1 and opt piecewise configs into 3 explicitly if that is desired.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This default is intentional and was confirmed with the PCG maintainer, Liji. We want TorchCompileConfig to default to three streams, including compile-only configurations, so I’ll keep it unchanged.


captured_args = tuple(make_weak_ref(arg) for arg in args)
captured_kwargs = {key: make_weak_ref(value) for key, value in kwargs.items()}
captured_output = make_weak_ref(output)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bridge output must retain owning storage. It is allocated after _end_current_segment(), so unlike captured_args produced by the preceding graph segment it is not pinned by a CUDAGraph private pool. make_weak_ref() retains only its raw pointer; once wrapper returns, the caching allocator may reuse the original allocation, and replay then copies into a stale/reassigned address before the next segment reads it. The cited SGLang implementation deliberately keeps this output strongly referenced for this reason. Please add an allocator-churn replay test as well.

Suggested change
captured_output = make_weak_ref(output)
captured_output = output

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. The eager output is allocated outside the graph-private pool and must retain owning storage. I changed it to a strong reference and added a weakref/allocator-churn replay regression test.

Signed-off-by: GuanhuaWang2001 <300454435+GuanhuaWang2001@users.noreply.github.com>
@GuanhuaWang2001

Copy link
Copy Markdown
Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65296 [ run ] triggered by Bot. Commit: 4bf70af Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65296 [ run ] completed with state FAILURE. Commit: 4bf70af
/LLM/main/L0_MergeRequest_PR pipeline #53072 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@GuanhuaWang2001

Copy link
Copy Markdown
Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65460 [ run ] triggered by Bot. Commit: 4bf70af Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #65460 [ run ] completed with state FAILURE. Commit: 4bf70af
/LLM/main/L0_MergeRequest_PR pipeline #53210 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api-breaking Accepted LLM API contract change that is backwards-incompatible ci: full pre-merge approved

Projects

None yet

Development

Successfully merging this pull request may close these issues.