Skip to content
Merged
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
60ad65f
[None][perf] AutoDeploy: replay SSM kernel for MTP extend path
galagam May 4, 2026
8be13b2
fix low_memory_overrides in integ test
galagam May 17, 2026
ddc7596
[None][fix] adp_router: restore get_relax_value fix lost during rebase
galagam May 17, 2026
be37bec
[None][perf] AutoDeploy: add WS=4 MTP config and unify mamba_ssm_cach…
galagam May 17, 2026
5ee80f2
[None][fix] narrow FlashInfer SSD eligibility gate
galagam May 22, 2026
ff42356
[None][refactor] remove kwargs routing from flashinfer_ssm; make all …
galagam May 24, 2026
142d750
[None][refactor] move SSM replay mode flag into BatchInfo
galagam May 24, 2026
0192059
[None][fix] flashinfer_ssm: fix head-dim validation and replay buffer…
galagam May 24, 2026
c397065
[None][fix] assert replay bundle completeness in _identify_managed_st…
galagam May 24, 2026
8911587
[None][test] add extend+replay unit test for flashinfer_cached_ssm
galagam May 24, 2026
58c3bec
[None][cleanup] drop redundant slot_idx alias comments in flashinfer_…
galagam May 24, 2026
534079d
[None][test] add flashinfer_mamba_cached_op to B200 CI
galagam May 24, 2026
ad62b70
[None][fix] low_memory_overrides: set batch_sizes and max_batch_size …
galagam May 24, 2026
f9c7c87
drop changes committed by mistake
galagam May 28, 2026
cba8ba6
Merge branch 'main' into gagam/super-mtp-perf-2-replay
galagam May 28, 2026
684f72f
fix merge
galagam May 28, 2026
97788c2
Merge branch 'main' into gagam/super-mtp-perf-2-replay
galagam Jun 2, 2026
fa5c865
improved comments
galagam Jun 1, 2026
ae7c388
remove accidentally committed file
galagam Jun 2, 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
11 changes: 6 additions & 5 deletions examples/auto_deploy/model_registry/configs/super_v3_mtp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
#
runtime: trtllm
compile_backend: torch-cudagraph
max_batch_size: 128
max_seq_len: 65536 # tunable
max_batch_size: 64
max_seq_len: 8192 # tunable
max_num_tokens: 2048
enable_chunked_prefill: false # TODO: Support chunked prefill w/ spec dec
attn_backend: trtllm
model_factory: AutoModelForCausalLM
skip_loading_weights: false
cuda_graph_config:
batch_sizes: [1, 2, 4, 8, 16, 24, 32, 64, 128]
max_batch_size: 64
Comment thread
galagam marked this conversation as resolved.
enable_padding: true
kv_cache_config:
# tunable mamba cache dtype
# --> use float32 for accuracy and default (auto) for speed
mamba_ssm_cache_dtype: auto
speculative_config:
decoding_type: MTP
Expand Down Expand Up @@ -54,6 +54,7 @@ transforms:
# for speculative Mamba state caching in this configuration.
insert_cached_ssm_attention:
backend: flashinfer_ssm
ssm_replay: true
insert_cached_causal_conv:
backend: triton_causal_conv
fuse_nvfp4_moe:
Expand Down
160 changes: 158 additions & 2 deletions tensorrt_llm/_torch/auto_deploy/custom_ops/attention_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ class BatchInfo:
Args:
batch_info_host: The batch info tensor on the host.

The information is stored in a 12-element batch_info_host tensor as follows:
The information is stored in a 14-element batch_info_host tensor as follows:

Slots 0-5 (batch composition):
- [0] num_prefill: number of prefill requests
Expand All @@ -425,10 +425,13 @@ class BatchInfo:
Slot 12 (spec-decoding info, set once at runtime init):
- [12] max_draft_len: maximum draft length per request (0 when not spec dec)

Slot 13 (replay mode flag, set once at runtime init):
- [13] use_replay: 1 if SSM replay state-update path is active, 0 otherwise

All fields can be accessed and updated with the convenience functions below.
"""

_NUM_ELEMENTS = 13
_NUM_ELEMENTS = 14

def __init__(self, batch_info_host: Optional[torch.Tensor] = None):
if batch_info_host is None:
Expand Down Expand Up @@ -551,6 +554,16 @@ def update_max_draft_len(self, max_draft_len: int) -> None:
def get_max_draft_len(self) -> int:
return int(self._batch_info[12])

# --- replay mode flag (slot 13) writer ---

def update_use_replay(self, use_replay: bool) -> None:
self._batch_info[13] = int(use_replay)

# --- replay mode flag (slot 13) reader ---

def is_use_replay(self) -> bool:
return bool(self._batch_info[13])


class SequenceInfo:
"""An interface to hold information about how the sequence is laid out and stored in cache.
Expand Down Expand Up @@ -2098,6 +2111,149 @@ def from_base(cls, base: Optional["SSMResourceHandler"]) -> Optional["SpecSSMRes
)


class ReplayOldXHandler(StateResourceHandler):
"""Per-layer old_x cache for the replay SSM kernel (single-buffered, bf16).

Shape: (max_batch, T, num_heads, head_dim) — T is determined by the manager's
spec_config (max_draft_len + 1), not by this handler. Acts as a type marker.
Routes to MambaHybridCacheManager via get_replay_old_x(layer_idx).
"""

def __init__(self, num_heads: int, head_dim: int, dtype: torch.dtype) -> None:
self.num_heads = num_heads
self.head_dim = head_dim
super().__init__(dtype=dtype)

@property
def state_shape(self) -> Tuple[int, int]:
return (self.num_heads, self.head_dim)

def allocate(self, sequence_info) -> torch.Tensor:
raise RuntimeError("ReplayOldXHandler must be backed by MambaHybridCacheManager")

def __eq__(self, other) -> bool:
return (
isinstance(other, ReplayOldXHandler)
and self.num_heads == other.num_heads
and self.head_dim == other.head_dim
and self.dtype == other.dtype
)


class ReplayOldBHandler(StateResourceHandler):
"""Per-layer old_B cache for the replay SSM kernel (double-buffered, bf16).

Shape: (max_batch, 2, T, n_groups, d_state) — T from manager.
Routes to MambaHybridCacheManager via get_replay_old_B(layer_idx).
"""

def __init__(self, n_groups: int, d_state: int, dtype: torch.dtype) -> None:
self.n_groups = n_groups
self.d_state = d_state
super().__init__(dtype=dtype)

@property
def state_shape(self) -> Tuple[int, int]:
return (self.n_groups, self.d_state)

def allocate(self, sequence_info) -> torch.Tensor:
raise RuntimeError("ReplayOldBHandler must be backed by MambaHybridCacheManager")

def __eq__(self, other) -> bool:
return (
isinstance(other, ReplayOldBHandler)
and self.n_groups == other.n_groups
and self.d_state == other.d_state
and self.dtype == other.dtype
)


class ReplayOldDtHandler(StateResourceHandler):
"""Per-layer old_dt cache for the replay SSM kernel (double-buffered, fp32).

Shape: (max_batch, 2, num_heads, T) — T from manager.
Routes to MambaHybridCacheManager via get_replay_old_dt(layer_idx).
"""

def __init__(self, num_heads: int) -> None:
self.num_heads = num_heads
super().__init__(dtype=torch.float32)

@property
def state_shape(self) -> Tuple[int]:
return (self.num_heads,)

def allocate(self, sequence_info) -> torch.Tensor:
raise RuntimeError("ReplayOldDtHandler must be backed by MambaHybridCacheManager")

def __eq__(self, other) -> bool:
return isinstance(other, ReplayOldDtHandler) and self.num_heads == other.num_heads


class ReplayOldDAcumsumHandler(StateResourceHandler):
"""Per-layer old_dA_cumsum cache for the replay SSM kernel (double-buffered, fp32).

Shape: (max_batch, 2, num_heads, T) — T from manager.
Routes to MambaHybridCacheManager via get_replay_old_dA_cumsum(layer_idx).
"""

def __init__(self, num_heads: int) -> None:
self.num_heads = num_heads
super().__init__(dtype=torch.float32)

@property
def state_shape(self) -> Tuple[int]:
return (self.num_heads,)

def allocate(self, sequence_info) -> torch.Tensor:
raise RuntimeError("ReplayOldDAcumsumHandler must be backed by MambaHybridCacheManager")

def __eq__(self, other) -> bool:
return isinstance(other, ReplayOldDAcumsumHandler) and self.num_heads == other.num_heads


class ReplayCacheBufIdxHandler(StateResourceHandler):
"""Global cache_buf_idx tensor for the replay SSM kernel (shared across all layers, int32).

Shape: (max_batch,). Routes to MambaHybridCacheManager.get_replay_cache_buf_idx().
The same tensor is returned for every SSM layer — the FX graph has one constant-address
input per layer, all pointing to the same buffer.
"""

def __init__(self) -> None:
super().__init__(dtype=torch.int32)

@property
def state_shape(self) -> Tuple[()]:
return ()

def allocate(self, sequence_info) -> torch.Tensor:
raise RuntimeError("ReplayCacheBufIdxHandler must be backed by MambaHybridCacheManager")

def __eq__(self, other) -> bool:
return isinstance(other, ReplayCacheBufIdxHandler)


class ReplayPrevNumAcceptedHandler(StateResourceHandler):
"""Global prev_num_accepted_tokens tensor for the replay SSM kernel (int32, shared).

Shape: (max_batch,). Routes to MambaHybridCacheManager.get_replay_prev_num_accepted_tokens().
"""

def __init__(self) -> None:
super().__init__(dtype=torch.int32)

@property
def state_shape(self) -> Tuple[()]:
return ()

def allocate(self, sequence_info) -> torch.Tensor:
raise RuntimeError("ReplayPrevNumAcceptedHandler must be backed by MambaHybridCacheManager")

def __eq__(self, other) -> bool:
return isinstance(other, ReplayPrevNumAcceptedHandler)


class SpecCausalConvResourceHandler(StateResourceHandler):
"""Intermediate conv state cache descriptor for speculative decoding.

Expand Down
Loading
Loading