main
py 73 lines 2.82 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 from types import SimpleNamespace
5
6 import pytest
7 import torch
8
9 from tests.v1.attention.utils import BatchSpec, create_common_attn_metadata
10 from vllm.config import CUDAGraphMode
11 from vllm.platforms import current_platform
12 from vllm.v1.attention.backends.triton_attn import TritonAttentionMetadataBuilder
13 from vllm.v1.attention.backends.triton_attn_diffkv import (
14 TritonAttentionDiffKVMetadataBuilder,
15 )
16 from vllm.v1.kv_cache_interface import FullAttentionSpec
17
18
19 # 64 segments only while num_seqs * num_kv_heads * 16 < 188 SMs on SM12.0 and
20 # the 64-segment scratch holds every query token (e.g. multi-query verify).
21 @pytest.mark.parametrize(
22 "builder_cls",
23 [TritonAttentionMetadataBuilder, TritonAttentionDiffKVMetadataBuilder],
24 )
25 @pytest.mark.parametrize(
26 "capability,num_kv_heads,num_seqs,query_len,segments",
27 [
28 ((12, 0), 1, 11, 1, 64),
29 ((12, 0), 1, 12, 1, 16),
30 ((12, 0), 8, 1, 1, 64),
31 ((12, 0), 8, 2, 1, 16),
32 ((9, 0), 1, 1, 1, 16),
33 ((12, 0), 1, 2, 4, 64),
34 ((12, 0), 1, 10, 4, 16),
35 ],
36 )
37 def test_split_k_segments_follow_sm_occupancy(
38 monkeypatch, builder_cls, capability, num_kv_heads, num_seqs, query_len, segments
39 ):
40 monkeypatch.setattr(current_platform, "is_cuda", lambda: True)
41 monkeypatch.setattr(
42 current_platform, "is_device_capability", lambda cap: cap == capability
43 )
44 monkeypatch.setattr(current_platform, "num_compute_units", lambda: 188)
45 config = SimpleNamespace(
46 model_config=SimpleNamespace(
47 get_num_attention_heads=lambda _: 8,
48 get_num_kv_heads=lambda _: num_kv_heads,
49 get_head_size=lambda: 128,
50 rswa_window=None,
51 ),
52 parallel_config=None,
53 scheduler_config=SimpleNamespace(max_num_seqs=16),
54 speculative_config=None,
55 compilation_config=SimpleNamespace(
56 cudagraph_mode=CUDAGraphMode.NONE, static_forward_context={}
57 ),
58 )
59 spec = FullAttentionSpec(
60 block_size=16, num_kv_heads=num_kv_heads, head_size=128, dtype=torch.bfloat16
61 )
62 builder = builder_cls(spec, ["layer.0"], config, "cpu")
63 batch = BatchSpec(seq_lens=[128] * num_seqs, query_lens=[query_len] * num_seqs)
64 metadata = builder.build(0, create_common_attn_metadata(batch, 16, "cpu"))
65 assert metadata.num_par_softmax_segments == segments
66 assert metadata.softmax_segm_output.shape[2] == segments
67 assert metadata.softmax_segm_max.shape[0] >= num_seqs * query_len
68 # DiffKV re-allocates the output; it must stay sized like the base buffers.
69 assert builder.softmax_segm_output.shape[0] == builder.softmax_segm_max.shape[0]
70 assert (
71 metadata.softmax_segm_output.data_ptr()
72 == builder.softmax_segm_output.data_ptr()
73 )