Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8bbfc17cf9 |
@@ -268,11 +268,39 @@ class DeepseekV32IndexerMetadataBuilder(AttentionMetadataBuilder):
|
||||
num_reqs=reqs_end - reqs_start,
|
||||
)
|
||||
|
||||
def build_for_drafting(
|
||||
self,
|
||||
common_attn_metadata: CommonAttentionMetadata,
|
||||
draft_index: int,
|
||||
) -> DeepseekV32IndexerMetadata:
|
||||
"""Build indexer metadata for draft model.
|
||||
|
||||
During drafting, each forward pass generates only 1 token per request,
|
||||
so we set offsets=None (no speculative decoding offsets needed).
|
||||
"""
|
||||
return self._build_impl(
|
||||
common_attn_metadata=common_attn_metadata,
|
||||
fast_build=True,
|
||||
drafting=True,
|
||||
)
|
||||
|
||||
def build(
|
||||
self,
|
||||
common_prefix_len: int,
|
||||
common_attn_metadata: CommonAttentionMetadata,
|
||||
fast_build: bool = False,
|
||||
) -> DeepseekV32IndexerMetadata:
|
||||
return self._build_impl(
|
||||
common_attn_metadata=common_attn_metadata,
|
||||
fast_build=fast_build,
|
||||
drafting=False,
|
||||
)
|
||||
|
||||
def _build_impl(
|
||||
self,
|
||||
common_attn_metadata: CommonAttentionMetadata,
|
||||
fast_build: bool = False,
|
||||
drafting: bool = False,
|
||||
) -> DeepseekV32IndexerMetadata:
|
||||
num_reqs = common_attn_metadata.num_reqs
|
||||
num_tokens = common_attn_metadata.num_actual_tokens
|
||||
@@ -331,11 +359,18 @@ class DeepseekV32IndexerMetadataBuilder(AttentionMetadataBuilder):
|
||||
# - top_k_per_row_decode wins for batch > 128 or seq_len <= 8K
|
||||
use_large_context_topk = batch_size <= 128 and _is_large_context
|
||||
|
||||
next_n = 1 + self.num_speculative_tokens
|
||||
if next_n > 1:
|
||||
offsets = torch.arange(next_n, device=self.device, dtype=torch.int32)
|
||||
else:
|
||||
if drafting:
|
||||
# During drafting, each forward generates 1 token per request,
|
||||
# so no speculative offsets are needed.
|
||||
offsets = None
|
||||
else:
|
||||
next_n = 1 + self.num_speculative_tokens
|
||||
if next_n > 1:
|
||||
offsets = torch.arange(
|
||||
next_n, device=self.device, dtype=torch.int32
|
||||
)
|
||||
else:
|
||||
offsets = None
|
||||
|
||||
seq_lens = common_attn_metadata.seq_lens[:num_decodes]
|
||||
if is_deep_gemm_supported():
|
||||
|
||||
@@ -547,10 +547,14 @@ class SpecDecodeBaseProposer:
|
||||
num_tokens_unpadded=batch_size, num_tokens_padded=batch_size
|
||||
)
|
||||
|
||||
cudagraph_runtime_mode, batch_desc = self.cudagraph_dispatcher.dispatch(
|
||||
batch_size_dp_padded
|
||||
)
|
||||
input_batch_size = batch_desc.num_tokens
|
||||
# Disable CUDA graphs for draft loop iterations.
|
||||
# When CUDA graphs pad the batch (e.g., 100 → 104), the MLA attention
|
||||
# backends call reshape_query_for_spec_decode(q, num_decodes) which
|
||||
# fails when padded_size % num_decodes != 0. Even when divisible,
|
||||
# padding positions contain invalid topk indices that cause CUDA
|
||||
# illegal memory access in the FlashMLA kernel.
|
||||
cudagraph_runtime_mode = CUDAGraphMode.NONE
|
||||
input_batch_size = batch_size_dp_padded
|
||||
if batch_size_across_dp is not None:
|
||||
batch_size_across_dp[self.dp_rank] = input_batch_size
|
||||
|
||||
@@ -653,6 +657,17 @@ class SpecDecodeBaseProposer:
|
||||
for layer_name in self.attn_layer_names:
|
||||
per_layer_attn_metadata[layer_name] = attn_metadata
|
||||
|
||||
# Rebuild indexer/DSA attention metadata for models like GLM5
|
||||
if self.draft_indexer_metadata_builder:
|
||||
draft_indexer_metadata = (
|
||||
self.draft_indexer_metadata_builder.build_for_drafting(
|
||||
common_attn_metadata=common_attn_metadata,
|
||||
draft_index=token_index + 1,
|
||||
)
|
||||
)
|
||||
for layer_name in self.indexer_layer_names:
|
||||
per_layer_attn_metadata[layer_name] = draft_indexer_metadata
|
||||
|
||||
# copy inputs to buffer for cudagraph
|
||||
self.input_ids[:batch_size] = input_ids
|
||||
self._set_positions(batch_size, clamped_positions)
|
||||
|
||||
Reference in New Issue
Block a user