Skip to content

Commit 7d2fac7

Browse files
committed
Fix MLA DCP spec decode metadata
Signed-off-by: Pavani Majety <pmajety@nvidia.com>
1 parent 09b8e7f commit 7d2fac7

3 files changed

Lines changed: 77 additions & 35 deletions

File tree

tests/v1/attention/test_mla_backends.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,59 @@ def fake_get_mla_metadata_dense_fp8(
882882
assert fp8_call is None
883883

884884

885+
def test_flashinfer_mla_dcp_spec_decode_keeps_reorder_threshold():
886+
builder_cls, _ = try_get_attention_backend(AttentionBackendEnum.FLASHINFER_MLA)
887+
888+
from vllm.config import SpeculativeConfig
889+
890+
class _DummyPrefillBackend:
891+
def clone(self):
892+
return self
893+
894+
vllm_config = create_vllm_config(
895+
model_name="deepseek-ai/DeepSeek-R1",
896+
tensor_parallel_size=1,
897+
max_model_len=1024,
898+
max_num_batched_tokens=512,
899+
hf_config_override={
900+
"num_attention_heads": 128,
901+
"num_key_value_heads": 128,
902+
"hidden_size": 7168,
903+
"qk_nope_head_dim": 128,
904+
"qk_rope_head_dim": 64,
905+
"v_head_dim": 128,
906+
"kv_lora_rank": 512,
907+
},
908+
)
909+
vllm_config.parallel_config.decode_context_parallel_size = 4
910+
vllm_config.speculative_config = SpeculativeConfig(
911+
method="ngram", num_speculative_tokens=3
912+
)
913+
vllm_config.compilation_config.static_forward_context["layer.0"] = SimpleNamespace(
914+
prefill_backend=_DummyPrefillBackend()
915+
)
916+
917+
kv_cache_spec = MLAAttentionSpec(
918+
block_size=32,
919+
num_kv_heads=vllm_config.model_config.get_num_kv_heads(
920+
vllm_config.parallel_config
921+
),
922+
head_size=vllm_config.model_config.get_head_size(),
923+
dtype=vllm_config.model_config.dtype,
924+
sliding_window=vllm_config.model_config.get_sliding_window(),
925+
cache_dtype_str="fp8",
926+
)
927+
928+
builder = builder_cls(
929+
kv_cache_spec,
930+
["layer.0"],
931+
vllm_config,
932+
torch.device("cpu"),
933+
)
934+
935+
assert builder.reorder_batch_threshold == 4
936+
937+
885938
def run_attention_backend(
886939
backend: AttentionBackendEnum,
887940
kv_cache_spec: MLAAttentionSpec,

vllm/v1/attention/backends/mla/flashinfer_mla.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-License-Identifier: Apache-2.0
22
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
33

4-
from typing import ClassVar
4+
from typing import TYPE_CHECKING, ClassVar
55

66
import torch
77
from flashinfer.decode import trtllm_batch_decode_with_kv_cache_mla
@@ -25,6 +25,10 @@
2525
)
2626
from vllm.v1.attention.backends.utils import KVCacheLayoutType
2727

28+
if TYPE_CHECKING:
29+
from vllm.config import VllmConfig
30+
from vllm.v1.kv_cache_interface import AttentionSpec
31+
2832
logger = init_logger(__name__)
2933

3034
FLASHINFER_MLA_WORKSPACE_BUFFER_SIZE = 128 * 1024 * 1024
@@ -52,6 +56,22 @@ class FlashInferMLAMetadataBuilder(MLACommonMetadataBuilder[MLACommonMetadata]):
5256
_cudagraph_support: ClassVar[AttentionCGSupport] = AttentionCGSupport.UNIFORM_BATCH
5357
query_len_support: ClassVar[QueryLenSupport] = QueryLenSupport.UNIFORM
5458

59+
def __init__(
60+
self,
61+
kv_cache_spec: "AttentionSpec",
62+
layer_names: list[str],
63+
vllm_config: "VllmConfig",
64+
device: torch.device,
65+
) -> None:
66+
super().__init__(
67+
kv_cache_spec,
68+
layer_names,
69+
vllm_config,
70+
device,
71+
MLACommonMetadata,
72+
supports_dcp_with_varlen=True,
73+
)
74+
5575

5676
class FlashInferMLABackend(MLACommonBackend):
5777
supported_dtypes: ClassVar[list[torch.dtype]] = [torch.float16, torch.bfloat16]

vllm/v1/attention/backends/mla/tokenspeed_mla.py

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@
2323
AttentionType,
2424
MultipleOf,
2525
)
26-
from vllm.v1.attention.backends.utils import (
27-
KVCacheLayoutType,
28-
get_dcp_local_seq_lens,
29-
)
26+
from vllm.v1.attention.backends.utils import KVCacheLayoutType
3027

3128
if TYPE_CHECKING:
3229
from vllm.config import VllmConfig
@@ -263,9 +260,7 @@ def forward_mqa(
263260
causal_seqs = attn_metadata.decode.dcp_tot_seq_lens
264261

265262
# tokenspeed_mla_decode expects query shape
266-
# (num_decodes, q_len_per_request, num_heads, head_dim). Under DCP,
267-
# multi-token speculative decode must be split into one-token rows:
268-
# local(G-k) is not local(G)-k in interleaved DCP layout.
263+
# (num_decodes, q_len_per_request, num_heads, head_dim).
269264
if num_decode_tokens % num_decodes != 0:
270265
logger.warning_once(
271266
"""TokenspeedMLAImpl got a query of uneven length.
@@ -274,33 +269,7 @@ def forward_mqa(
274269
)
275270
q = q.unsqueeze(1)
276271
else:
277-
tokens_per_req = num_decode_tokens // num_decodes
278-
if self.dcp_world_size > 1 and tokens_per_req > 1:
279-
assert causal_seqs is not None
280-
offsets = torch.arange(
281-
1 - tokens_per_req,
282-
1,
283-
device=causal_seqs.device,
284-
dtype=causal_seqs.dtype,
285-
)
286-
causal_seqs = (
287-
causal_seqs[:num_decodes].unsqueeze(1) + offsets
288-
).flatten()
289-
seq_lens = get_dcp_local_seq_lens(
290-
causal_seqs,
291-
self.dcp_world_size,
292-
self.dcp_rank,
293-
self.cp_kv_cache_interleave_size,
294-
)
295-
block_tables = (
296-
block_tables[:num_decodes]
297-
.unsqueeze(1)
298-
.expand(-1, tokens_per_req, -1)
299-
.reshape(num_decode_tokens, -1)
300-
)
301-
q = q.view(num_decode_tokens, 1, q.shape[-2], q.shape[-1])
302-
else:
303-
q = q.view(num_decodes, -1, q.shape[-2], q.shape[-1])
272+
q = q.view(num_decodes, -1, q.shape[-2], q.shape[-1])
304273

305274
if self.softmax_scale is None:
306275
# FP8 KV cache is mandatory for this backend, so q_scale/k_scale

0 commit comments

Comments
 (0)