[KDA] Add target_verify support for speculative decoding (#26888)
Co-authored-by: yuyanqi <yuyanqi@meituan.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Xinyuan Tong <xinyuantong.cs@gmail.com>
This commit is contained in:
co-authored by
yuyanqi
Claude Opus 4.6
Xinyuan Tong
parent
7c4b22fae5
commit
a678a42033
@@ -403,6 +403,11 @@ class KDAAttnBackend(MambaAttnBackendBase):
|
||||
|
||||
ssm_states = mamba_cache_params.temporal
|
||||
|
||||
# Normal extend path
|
||||
if forward_batch.extend_prefix_lens is None:
|
||||
raise RuntimeError(
|
||||
"extend_prefix_lens cannot be None in non-TARGET_VERIFY mode."
|
||||
)
|
||||
has_initial_state = forward_batch.extend_prefix_lens > 0
|
||||
|
||||
if self.forward_metadata.has_mamba_track_mask:
|
||||
|
||||
@@ -381,6 +381,34 @@ class MambaPool:
|
||||
intermediate_ssm: Optional[torch.Tensor]
|
||||
intermediate_conv_window: List[torch.Tensor]
|
||||
|
||||
def _detect_conv_window_axis(
|
||||
self, conv_state_shape: List[Tuple[int, int]], win_len: int
|
||||
) -> int:
|
||||
"""Prefer GDN's trailing axis when both match; mixed layer layouts cannot
|
||||
share one overlapping conv-window buffer.
|
||||
"""
|
||||
axis = None
|
||||
for conv_shape in conv_state_shape:
|
||||
if conv_shape[-1] == win_len:
|
||||
shape_axis = len(conv_shape) - 1
|
||||
elif conv_shape[0] == win_len:
|
||||
shape_axis = 0
|
||||
else:
|
||||
raise ValueError(
|
||||
f"conv_state shape {conv_shape} has no axis of length "
|
||||
f"conv_kernel-1={win_len}; cannot build the deduplicated "
|
||||
"sliding-window conv-intermediate view."
|
||||
)
|
||||
if axis is None:
|
||||
axis = shape_axis
|
||||
elif axis != shape_axis:
|
||||
raise ValueError(
|
||||
"inconsistent conv-window axis across conv shapes "
|
||||
f"{conv_state_shape}; a single conv_window_axis cannot serve "
|
||||
"mixed layouts."
|
||||
)
|
||||
return axis
|
||||
|
||||
def _allocate_deduplicated_conv_window(
|
||||
self,
|
||||
*,
|
||||
@@ -676,6 +704,10 @@ class MambaPool:
|
||||
)
|
||||
self._intermediate_conv_window_phys = []
|
||||
if dedup_conv_window:
|
||||
win_len = cache_params.shape.conv_kernel - 1
|
||||
self.conv_window_axis = self._detect_conv_window_axis(
|
||||
conv_state_shape, win_len
|
||||
)
|
||||
intermediate_conv_window_cache = []
|
||||
for conv_shape in conv_state_shape:
|
||||
phys, view = self._allocate_deduplicated_conv_window(
|
||||
|
||||
@@ -382,10 +382,12 @@ class KimiDeltaAttention(nn.Module):
|
||||
hidden_states
|
||||
)
|
||||
|
||||
# For prefill: raw gate is passed to chunk_kda_fwd, which fuses gate
|
||||
# activation with chunk_local_cumsum (kda_gate_chunk_cumsum kernel).
|
||||
# For decode: gate activation is handled inside fused_recurrent kernel.
|
||||
if not forward_batch.forward_mode.is_decode():
|
||||
# Prefill passes raw gates to chunk KDA; decode and target-verify kernels
|
||||
# apply the activation internally.
|
||||
if (
|
||||
not forward_batch.forward_mode.is_decode()
|
||||
and not forward_batch.forward_mode.is_target_verify()
|
||||
):
|
||||
forget_gate = forget_gate.unflatten(
|
||||
-1, (-1, self.head_dim)
|
||||
) # [T, H*K] -> [T, H, K]
|
||||
|
||||
Reference in New Issue
Block a user