Skip to content

Commit aac884c

Browse files
committed
Add tests for CUDA graph profiling cache sizing
1 parent 6177d1a commit aac884c

2 files changed

Lines changed: 109 additions & 20 deletions

File tree

tests/v1/worker/test_gpu_model_runner.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
KVCacheConfig,
4343
KVCacheGroupSpec,
4444
KVCacheTensor,
45+
MambaSpec,
4546
)
4647
from vllm.v1.outputs import EMPTY_MODEL_RUNNER_OUTPUT
4748
from vllm.v1.sample.metadata import SamplingMetadata
@@ -240,6 +241,80 @@ def _make_kv_cache_spec() -> FullAttentionSpec:
240241
return FullAttentionSpec(block_size=1, num_kv_heads=1, head_size=1, dtype="float16")
241242

242243

244+
def test_minimal_cudagraph_profiling_blocks_scales_tokens_to_blocks():
245+
attn_spec = FullAttentionSpec(
246+
block_size=592,
247+
num_kv_heads=4,
248+
head_size=128,
249+
dtype=torch.float16,
250+
)
251+
groups = [KVCacheGroupSpec(["attn"], attn_spec)]
252+
253+
min_blocks, has_mamba_cache = (
254+
GPUModelRunner._get_minimal_kv_cache_blocks_for_cudagraph_profiling(
255+
groups,
256+
max_capture_tokens=8192,
257+
max_num_reqs=8,
258+
cp_size=3,
259+
)
260+
)
261+
262+
assert min_blocks == 5 # ceil(8192 / (592 * 3))
263+
assert not has_mamba_cache
264+
265+
266+
def test_minimal_cudagraph_profiling_blocks_cover_mamba_cache_lines():
267+
attn_spec = FullAttentionSpec(
268+
block_size=592,
269+
num_kv_heads=4,
270+
head_size=128,
271+
dtype=torch.float16,
272+
)
273+
mamba_spec = MambaSpec(
274+
shapes=((256, 4),),
275+
dtypes=(torch.float16,),
276+
block_size=592,
277+
)
278+
groups = [
279+
KVCacheGroupSpec(["attn"], attn_spec),
280+
KVCacheGroupSpec(["mamba"], mamba_spec),
281+
]
282+
283+
min_blocks, has_mamba_cache = (
284+
GPUModelRunner._get_minimal_kv_cache_blocks_for_cudagraph_profiling(
285+
groups,
286+
max_capture_tokens=4096,
287+
max_num_reqs=8,
288+
cp_size=3,
289+
)
290+
)
291+
292+
assert min_blocks == 8 # max(ceil(4096 / (592 * 3)), max_num_reqs)
293+
assert has_mamba_cache
294+
295+
296+
def test_minimal_cudagraph_profiling_blocks_without_capture_size():
297+
attn_spec = FullAttentionSpec(
298+
block_size=16,
299+
num_kv_heads=4,
300+
head_size=128,
301+
dtype=torch.float16,
302+
)
303+
groups = [KVCacheGroupSpec(["attn"], attn_spec)]
304+
305+
min_blocks, has_mamba_cache = (
306+
GPUModelRunner._get_minimal_kv_cache_blocks_for_cudagraph_profiling(
307+
groups,
308+
max_capture_tokens=None,
309+
max_num_reqs=8,
310+
cp_size=1,
311+
)
312+
)
313+
314+
assert min_blocks == 1
315+
assert not has_mamba_cache
316+
317+
243318
def test_select_common_block_size_prefers_manager_block_size():
244319
backend_a = _make_mock_backend_for_kernel_block_size([MultipleOf(32)])
245320
backend_b = _make_mock_backend_for_kernel_block_size([64, MultipleOf(16)])

vllm/v1/worker/gpu_model_runner.py

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6425,6 +6425,31 @@ def profile_run(self) -> None:
64256425
self.encoder_cache.clear()
64266426
gc.collect()
64276427

6428+
@staticmethod
6429+
def _get_minimal_kv_cache_blocks_for_cudagraph_profiling(
6430+
kv_cache_groups: list[KVCacheGroupSpec],
6431+
max_capture_tokens: int | None,
6432+
max_num_reqs: int,
6433+
cp_size: int,
6434+
) -> tuple[int, bool]:
6435+
if max_capture_tokens is None:
6436+
return 1, False
6437+
6438+
block_requirements: list[int] = []
6439+
has_mamba_cache = False
6440+
for group in kv_cache_groups:
6441+
kv_cache_spec = group.kv_cache_spec
6442+
if isinstance(kv_cache_spec, EncoderOnlyAttentionSpec):
6443+
continue
6444+
if isinstance(kv_cache_spec, MambaSpec):
6445+
has_mamba_cache = True
6446+
block_requirements.append(max_num_reqs)
6447+
else:
6448+
block_requirements.append(
6449+
cdiv(max_capture_tokens, kv_cache_spec.block_size * cp_size)
6450+
)
6451+
return max(1, *block_requirements), has_mamba_cache
6452+
64286453
def _init_minimal_kv_cache_for_profiling(self) -> None:
64296454
from vllm.v1.core.kv_cache_utils import (
64306455
get_kv_cache_config_from_groups,
@@ -6435,27 +6460,16 @@ def _init_minimal_kv_cache_for_profiling(self) -> None:
64356460
KVCacheSpecRegistry.check_kv_cache_spec_registry(kv_cache_spec)
64366461
kv_cache_groups = get_kv_cache_groups(self.vllm_config, kv_cache_spec)
64376462
max_capture_tokens = self.compilation_config.max_cudagraph_capture_size
6438-
if max_capture_tokens is None:
6439-
min_blocks = 1
6440-
else:
6441-
cp_size = get_total_cp_world_size()
6442-
block_requirements: list[int] = []
6443-
has_mamba_cache = False
6444-
for group in kv_cache_groups:
6445-
kv_cache_spec = group.kv_cache_spec
6446-
if isinstance(kv_cache_spec, EncoderOnlyAttentionSpec):
6447-
continue
6448-
if isinstance(kv_cache_spec, MambaSpec):
6449-
has_mamba_cache = True
6450-
block_requirements.append(self.max_num_reqs)
6451-
else:
6452-
block_requirements.append(
6453-
cdiv(max_capture_tokens, kv_cache_spec.block_size * cp_size)
6454-
)
6455-
min_blocks = max(
6456-
1,
6457-
*block_requirements,
6463+
cp_size = get_total_cp_world_size()
6464+
min_blocks, has_mamba_cache = (
6465+
self._get_minimal_kv_cache_blocks_for_cudagraph_profiling(
6466+
kv_cache_groups,
6467+
max_capture_tokens,
6468+
self.max_num_reqs,
6469+
cp_size,
64586470
)
6471+
)
6472+
if max_capture_tokens is not None:
64596473
logger.info(
64606474
"Using %d KV blocks for CUDA graph profiling "
64616475
"(max_capture_tokens=%d, cp_size=%d, has_mamba_cache=%s)",

0 commit comments

Comments
 (0)