|
| 1 | +# SPDX-License-Identifier: Apache-2.0 |
| 2 | +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project |
| 3 | +"""FlashInfer GQA builder: reorder threshold under DCP with spec decode.""" |
| 4 | + |
| 5 | +import pytest |
| 6 | +import torch |
| 7 | + |
| 8 | +from tests.v1.attention.utils import create_vllm_config |
| 9 | +from vllm.config import SpeculativeConfig |
| 10 | +from vllm.platforms import current_platform |
| 11 | +from vllm.v1.attention.backends import flashinfer as flashinfer_backend |
| 12 | +from vllm.v1.attention.backends.flashinfer import ( |
| 13 | + FlashInferDecodeKernel, |
| 14 | + FlashInferMetadataBuilder, |
| 15 | +) |
| 16 | +from vllm.v1.attention.backends.utils import PerLayerParameters |
| 17 | +from vllm.v1.kv_cache_interface import FullAttentionSpec |
| 18 | + |
| 19 | +if not current_platform.is_cuda(): |
| 20 | + pytest.skip("FlashInfer backend requires a CUDA platform.", allow_module_level=True) |
| 21 | + |
| 22 | + |
| 23 | +def test_flashinfer_gqa_dcp_spec_decode_clamps_reorder_threshold(monkeypatch): |
| 24 | + """trtllm-gen decode receives no cp_rank/global-seq-len information, so its |
| 25 | + end-aligned causal mask is wrong for q_len > 1 over the DCP-interleaved |
| 26 | + local KV shard. The builder must keep reorder_batch_threshold at 1 under |
| 27 | + DCP so spec queries take the (DCP-aware) prefill path instead. |
| 28 | + """ |
| 29 | + vllm_config = create_vllm_config(max_model_len=1024) |
| 30 | + vllm_config.parallel_config.decode_context_parallel_size = 2 |
| 31 | + vllm_config.speculative_config = SpeculativeConfig( |
| 32 | + method="ngram", num_speculative_tokens=3 |
| 33 | + ) |
| 34 | + |
| 35 | + monkeypatch.setattr( |
| 36 | + flashinfer_backend, "can_use_trtllm_attention", lambda *args, **kwargs: True |
| 37 | + ) |
| 38 | + monkeypatch.setattr( |
| 39 | + FlashInferMetadataBuilder, |
| 40 | + "_get_flashinfer_trtllm_api_decode_kernel", |
| 41 | + staticmethod(lambda: FlashInferDecodeKernel.TRTLLM_GEN), |
| 42 | + ) |
| 43 | + monkeypatch.setattr( |
| 44 | + flashinfer_backend, |
| 45 | + "get_per_layer_parameters", |
| 46 | + lambda *args, **kwargs: { |
| 47 | + "layer.0": PerLayerParameters( |
| 48 | + window_left=-1, logits_soft_cap=None, sm_scale=0.1, has_sinks=False |
| 49 | + ) |
| 50 | + }, |
| 51 | + ) |
| 52 | + |
| 53 | + kv_cache_spec = FullAttentionSpec( |
| 54 | + block_size=16, |
| 55 | + num_kv_heads=vllm_config.model_config.get_num_kv_heads( |
| 56 | + vllm_config.parallel_config |
| 57 | + ), |
| 58 | + head_size=vllm_config.model_config.get_head_size(), |
| 59 | + dtype=vllm_config.model_config.dtype, |
| 60 | + ) |
| 61 | + builder = FlashInferMetadataBuilder( |
| 62 | + kv_cache_spec, |
| 63 | + ["layer.0"], |
| 64 | + vllm_config, |
| 65 | + torch.device("cpu"), |
| 66 | + ) |
| 67 | + |
| 68 | + # Guard against passing vacuously with the kernel disabled. |
| 69 | + assert ( |
| 70 | + builder.flashinfer_trtllm_api_decode_kernel == FlashInferDecodeKernel.TRTLLM_GEN |
| 71 | + ) |
| 72 | + assert builder.reorder_batch_threshold == 1 |
0 commit comments