Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
0ae1f5c
BCG V1
GuanhuaWang2001 Jul 20, 2026
285a75a
bcg v2, support more model, fix adp bug and dsv4 bug
GuanhuaWang2001 Jul 21, 2026
043bee6
[07/23/14:03] share BCG pool across segments
GuanhuaWang2001 Jul 23, 2026
367adcc
[07/23/16:37] benchmark DSV4 1P1D AAAgent with BCG
GuanhuaWang2001 Jul 23, 2026
9a3b356
chore: checkpoint MLA epilogue fusion draft
GuanhuaWang2001 Jul 24, 2026
e1992b4
[07/24/20:09] refactor DSv4 BCG epilogue fusion
GuanhuaWang2001 Jul 24, 2026
f6c937e
fix bcg and epilogue
GuanhuaWang2001 Jul 27, 2026
9514e3d
rename some var name to make mla more clear
GuanhuaWang2001 Jul 28, 2026
cf7bfae
[None][test] add focused BCG accuracy coverage
GuanhuaWang2001 Jul 28, 2026
3e5aa46
[None][chore] apply pre-commit fixes to BCG changes
GuanhuaWang2001 Jul 29, 2026
8ce084f
[None][fix] preserve PCG behavior with breakable CUDA graphs
GuanhuaWang2001 Jul 29, 2026
7da1cfc
[None][test] remove DeepSeek V4 BCG accuracy tests
GuanhuaWang2001 Jul 30, 2026
a22a553
[None][fix] repair BCG tests after rebase
GuanhuaWang2001 Aug 3, 2026
d984f98
[None][fix] avoid implicit legacy PCG bucket conflicts
GuanhuaWang2001 Aug 4, 2026
fae1d66
[None][fix] restrict eager graph captured values
GuanhuaWang2001 Aug 4, 2026
3b78448
reorganize tests
GuanhuaWang2001 Aug 4, 2026
1d4f0ee
[None][test] provide valid prepared graph inputs
GuanhuaWang2001 Aug 5, 2026
17d17e1
[None][fix] keep prefill warmup ranks aligned
GuanhuaWang2001 Aug 5, 2026
baa6174
[None][fix] simplify breakable CUDA graph helpers
GuanhuaWang2001 Aug 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions docs/source/features/torch_compile_and_piecewise_cuda_graph.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Torch Compile & Piecewise CUDA Graph
# Torch Compile & Prefill CUDA Graph

In this guide, we show how to enable torch.compile and Piecewise CUDA Graph in TensorRT LLM. TensorRT LLM uses torch.compile for lightweight vertical fusion and Piecewise CUDA Graph.

Expand Down Expand Up @@ -41,12 +41,29 @@ To enable torch.compile and Piecewise CUDA Graph, add the following configuratio

```yaml
... # Other extra config
prefill_cuda_graph_backend: piecewise
prefill_capture_num_tokens: '${capture_num_tokens}' # e.g. [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, ..., 3072]
torch_compile_config:
capture_num_tokens: '${capture_num_tokens}' # List of num tokens to capture. e.g., [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, ..., 3072]
enable_userbuffers: false
enable_piecewise_cuda_graph: true
```

`TorchCompileConfig.enable_piecewise_cuda_graph` and
`TorchCompileConfig.capture_num_tokens` are deprecated aliases for these
prefill-specific options.

The experimental breakable implementation can capture the model body without
torch.compile:

```yaml
prefill_cuda_graph_backend: breakable
prefill_capture_num_tokens: [128, 256, 512]
```

The first version of the breakable backend supports BF16 Qwen3.5 on one GPU for
context-only, tensor/pipeline parallelism and mixed context/decode batches with KV cache. Speculative
decoding, LoRA, multimodal inputs, and context
logits fall back to eager execution or are rejected during initialization.

## Tips for Piecewise CUDA Graph

### Piecewise CUDA Graph & Generation Only CUDA Graph
Expand All @@ -59,9 +76,10 @@ cuda_graph_config:
max_batch_size: 1024 # Specify max capture batch size for generation only cuda graph. By default, TensorRT LLM will generate a capture list based on it.

torch_compile_config:
capture_num_tokens: '${capture_num_tokens}' # Specify capture_num_tokens for piecewise cuda graph
enable_userbuffers: false
enable_piecewise_cuda_graph: true

prefill_cuda_graph_backend: piecewise
prefill_capture_num_tokens: '${capture_num_tokens}'
```

### Piecewise CUDA Graph Padding
Expand Down
4 changes: 2 additions & 2 deletions tensorrt_llm/_torch/compilation/piecewise_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from tensorrt_llm.llmapi.utils import enable_llm_debug

from ..utils import (get_model_extra_attrs,
get_per_request_piecewise_cuda_graph_flag,
get_per_request_prefill_cuda_graph_flag,
get_piecewise_cuda_graph_flag, make_weak_ref,
set_piecewise_running)
from .multi_stream.auto_multi_stream import multi_stream_schedule
Expand Down Expand Up @@ -202,7 +202,7 @@ def __call__(self, *args):
if (runtime_num_of_token is None
or runtime_num_of_token not in self.entries
or not get_piecewise_cuda_graph_flag()
or not get_per_request_piecewise_cuda_graph_flag()):
or not get_per_request_prefill_cuda_graph_flag()):
return self.default_callable(*args)

if self.is_first_runner or self.is_last_runner:
Expand Down
8 changes: 6 additions & 2 deletions tensorrt_llm/_torch/models/modeling_minimaxm3.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
)
from ..modules.multi_stream_utils import maybe_execute_in_parallel
from ..modules.rms_norm import RMSNorm
from ..pyexecutor.breakable_cuda_graph import eager_on_graph, is_in_breakable_cuda_graph
from ..utils import (
ActivationType,
AuxStreamType,
Expand Down Expand Up @@ -660,6 +661,9 @@ def minimax_m3_attn_custom_op_inplace(
)


maybe_bcg_minimax_m3_attn_custom_op_inplace = eager_on_graph(minimax_m3_attn_custom_op_inplace)


class MiniMaxM3Attention(Attention):
"""M3 attention: dense (layers 0-2) or sparse (layers 3-59).

Expand Down Expand Up @@ -1238,8 +1242,8 @@ def _forward_attention_core(
attn_metadata: AttentionMetadata,
) -> torch.Tensor:
output = q.new_empty((q.shape[0], self.num_heads * self.head_dim))
if self.register_to_config and is_torch_compiling():
minimax_m3_attn_custom_op_inplace(
if self.register_to_config and (is_torch_compiling() or is_in_breakable_cuda_graph()):
maybe_bcg_minimax_m3_attn_custom_op_inplace(
q,
k,
v,
Expand Down
20 changes: 12 additions & 8 deletions tensorrt_llm/_torch/modules/attention.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
cp_allgather, reducescatter)
from ..model_config import ModelConfig
from ..peft.lora.layer import LoraLayer, LoraModuleType
from ..pyexecutor.breakable_cuda_graph import (eager_on_graph,
is_in_breakable_cuda_graph)
from ..utils import (Fp4QuantizedTensor, get_model_extra_attrs,
is_nvfp4_marlin_enabled, is_torch_compiling)
from .linear import Linear, TensorParallelMode, WeightMode, WeightsLoadingConfig
Expand Down Expand Up @@ -115,6 +117,9 @@ def attn_custom_op_inplace(
)


maybe_bcg_attn_custom_op_inplace = eager_on_graph(attn_custom_op_inplace)


def _helix_zero_kv_mask(
attn_metadata: AttentionMetadata,
num_tokens: int,
Expand Down Expand Up @@ -932,20 +937,19 @@ def forward_impl(
if "mrope_position_deltas" in mrope_config:
mrope_position_deltas = mrope_config["mrope_position_deltas"]

# Currently only TRTLLM and FLASHINFER are torch compile compatible backends.
# Only enable custom inplace op when torch compiling.
use_custom_inplace_op = (self.register_to_config
and (self.attn_backend == "TRTLLM"
or self.attn_backend == "FLASHINFER")
and is_torch_compiling()
and not self.is_marlin_enabled)
# Currently only TRTLLM and FLASHINFER support the custom inplace op.
use_custom_inplace_op = (
self.register_to_config and
(self.attn_backend == "TRTLLM" or self.attn_backend == "FLASHINFER")
and (is_torch_compiling() or is_in_breakable_cuda_graph())
and not self.is_marlin_enabled)

if use_custom_inplace_op:
outputs = create_attn_outputs(q, attention_mask, self.layer_idx_str)
assert len(outputs) == 1 or len(outputs) == 2
output = outputs[0]
output_sf = outputs[1] if len(outputs) == 2 else None
attn_custom_op_inplace(
maybe_bcg_attn_custom_op_inplace(

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.

Why gdn need to separate PCG and DCG but attention don't?

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.

sorry i made mistakes. gdn dont need to separate PCG and BCG

q,
k,
v,
Expand Down
9 changes: 7 additions & 2 deletions tensorrt_llm/_torch/modules/mamba/gdn_mixer.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from ...attention_backend import AttentionMetadata
from ...distributed import AllReduceParams
from ...model_config import ModelConfig
from ...pyexecutor.breakable_cuda_graph import eager_on_graph, is_in_breakable_cuda_graph
from ...speculative import SpecMetadata
from ...utils import EventType, get_model_extra_attrs, is_gdn_replay_enabled, is_torch_compiling
from ..linear import FP8QDQLinearMethod, Linear, TensorParallelMode
Expand Down Expand Up @@ -174,6 +175,9 @@ def gdn_custom_op_inplace(
)


maybe_bcg_gdn_custom_op_inplace = eager_on_graph(gdn_custom_op_inplace)


def ensure_divisibility(numerator, denominator):
"""Ensure that numerator is divisible by the denominator."""
assert numerator % denominator == 0, "{} is not divisible by {}".format(numerator, denominator)
Expand Down Expand Up @@ -1053,11 +1057,12 @@ def forward(
):
mixed_qkv, z, a, b = self._compute_tokenwise_inputs(hidden_states)

if self.register_to_config and is_torch_compiling():
use_breakable_cuda_graph = not is_torch_compiling() and is_in_breakable_cuda_graph()
if self.register_to_config and (is_torch_compiling() or use_breakable_cuda_graph):
attn_out = mixed_qkv.new_empty(
(1, mixed_qkv.shape[0], self.num_v_heads_per_tp, self.head_v_dim)
)
gdn_custom_op_inplace(mixed_qkv, a, b, self.layer_idx_str, attn_out)
maybe_bcg_gdn_custom_op_inplace(mixed_qkv, a, b, self.layer_idx_str, attn_out)
else:
attn_out = self.forward_core(
mixed_qkv,
Expand Down
Loading
Loading