@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / 6cac54f4d1
Fork 0

A high-throughput and memory-efficient inference and serving engine for LLMs

Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git

Synced Nov 15, 07:15 UTC

[v1] Re-init input batch for multiple kv cache groups (#18654)

Signed-off-by: Chen Zhang <zhangch99@outlook.com>

Chen Zhang committed Jun 4, 2025 at 05:41 UTC 6cac54f4d1673991a415b9897d610c132104155b
6 files changed +61 -46
tests/v1/worker/test_gpu_input_batch.py
+3 -26
@@ -10,8 +10,6 @@ import torch
10
11 from vllm.sampling_params import SamplingParams
12 from vllm.utils import is_pin_memory_available, make_tensor_with_pad
13 -from vllm.v1.kv_cache_interface import (FullAttentionSpec, KVCacheConfig,
14 - KVCacheGroupSpec, KVCacheTensor)
13 from vllm.v1.sample.metadata import SamplingMetadata
14 from vllm.v1.worker.block_table import BlockTable, MultiGroupBlockTable
15 from vllm.v1.worker.gpu_input_batch import CachedRequestState, InputBatch
@@ -25,27 +23,6 @@ CUDA_DEVICES = [
23 MAX_NUM_PROMPT_TOKENS = 64
24
25
28 -def get_kv_cache_config() -> KVCacheConfig:
29 - return KVCacheConfig(
30 - num_blocks=10,
31 - tensors={
32 - "layer.0": KVCacheTensor(size=1024),
33 - },
34 - kv_cache_groups=[
35 - KVCacheGroupSpec(
36 - layer_names=["layer.0"],
37 - kv_cache_spec=FullAttentionSpec(
38 - block_size=1,
39 - num_kv_heads=1,
40 - head_size=16,
41 - dtype=torch.float16,
42 - use_mla=False,
43 - ),
44 - ),
45 - ],
46 - )
47 -
48 -
26 def _compare_objs(obj1, obj2):
27 attrs = inspect.getmembers(obj1, lambda a: not (inspect.isroutine(a)))
28 attr_names = set([
@@ -252,7 +229,7 @@ def test_sampling_metadata_in_input_batch(device: str, batch_size: int):
229 device=torch.device(device),
230 pin_memory=is_pin_memory_available(),
231 vocab_size=1024,
255 - block_size=1,
232 + block_sizes=[1],
233 )
234 reqs: list[CachedRequestState] = []
235 req_id_reqs = {}
@@ -342,7 +319,7 @@ def test_swap_states_in_input_batch(device: str, batch_size: int,
319 device=torch.device(device),
320 pin_memory=is_pin_memory_available(),
321 vocab_size=1024,
345 - block_size=1,
322 + block_sizes=[1],
323 )
324 ref_input_batch: InputBatch = InputBatch(
325 max_num_reqs=batch_size,
@@ -351,7 +328,7 @@ def test_swap_states_in_input_batch(device: str, batch_size: int,
328 device=torch.device(device),
329 pin_memory=is_pin_memory_available(),
330 vocab_size=1024,
354 - block_size=1,
331 + block_sizes=[1],
332 )
333
334 reqs: list[CachedRequestState] = []
tests/v1/worker/test_gpu_model_runner.py
+3 -1
@@ -54,7 +54,9 @@ def initialize_kv_cache(runner: GPUModelRunner):
54 device=runner.device,
55 pin_memory=runner.pin_memory,
56 vocab_size=runner.model_config.get_vocab_size(),
57 - block_size=kv_cache_config.kv_cache_groups[0].kv_cache_spec.block_size,
57 + block_sizes=[
58 + kv_cache_config.kv_cache_groups[0].kv_cache_spec.block_size
59 + ],
60 )
61 runner.initialize_attn_backend(kv_cache_config)
62
vllm/v1/worker/block_table.py
+2 -1
@@ -105,10 +105,11 @@ class MultiGroupBlockTable:
105
106 def __init__(self, max_num_reqs: int, max_model_len: int,
107 max_num_batched_tokens: int, pin_memory: bool,
108 - device: torch.device, block_size: int) -> None:
108 + device: torch.device, block_sizes: list[int]) -> None:
109 self.block_tables = [
110 BlockTable(max_num_reqs, cdiv(max_model_len, block_size),
111 max_num_batched_tokens, pin_memory, device)
112 + for block_size in block_sizes
113 ]
114
115 def append_row(self, block_ids: list[list[int]], row_idx: int) -> None:
vllm/v1/worker/gpu_input_batch.py
+9 -9
@@ -56,14 +56,14 @@ class CachedRequestState:
56 class InputBatch:
57
58 def __init__(
59 - self,
60 - max_num_reqs: int,
61 - max_model_len: int,
62 - max_num_batched_tokens: int,
63 - device: torch.device,
64 - pin_memory: bool,
65 - vocab_size: int,
66 - block_size: int,
59 + self,
60 + max_num_reqs: int,
61 + max_model_len: int,
62 + max_num_batched_tokens: int,
63 + device: torch.device,
64 + pin_memory: bool,
65 + vocab_size: int,
66 + block_sizes: list[int], # The block_size of each kv cache group
67 ):
68 self.max_num_reqs = max_num_reqs
69 self.max_model_len = max_model_len
@@ -105,7 +105,7 @@ class InputBatch:
105 max_num_batched_tokens=max_num_batched_tokens,
106 pin_memory=pin_memory,
107 device=device,
108 - block_size=block_size,
108 + block_sizes=block_sizes,
109 )
110
111 # Sampling-related.
vllm/v1/worker/gpu_model_runner.py
+40 -6
@@ -143,7 +143,6 @@ class GPUModelRunner(LoRAModelRunnerMixin):
143 self.attn_metadata_builders: list[AttentionMetadataBuilder] = []
144 self.attn_backends: list[type[AttentionBackend]] = []
145 # self.kv_cache_config: KVCacheConfig
146 - # self.input_batch: InputBatch # Persistent batch.
146
147 # req_id -> (input_id -> encoder_output)
148 self.encoder_cache: dict[str, dict[int, torch.Tensor]] = {}
@@ -173,6 +172,15 @@ class GPUModelRunner(LoRAModelRunnerMixin):
172 # Request states.
173 self.requests: dict[str, CachedRequestState] = {}
174
175 + # Input Batch
176 + # NOTE(Chen): Ideally, we should initialize the input batch inside
177 + # `initialize_kv_cache` based on the kv cache config. However, as in
178 + # https://github.com/vllm-project/vllm/pull/18298, due to some unknown
179 + # reasons, we have to initialize the input batch before `load_model`,
180 + # quantization + weight offloading will fail otherwise. As a temporary
181 + # solution, we initialize the input batch here, and re-initialize it
182 + # in `initialize_kv_cache` if the block_sizes here is different from
183 + # the block_sizes in the kv cache config.
184 self.input_batch = InputBatch(
185 max_num_reqs=self.max_num_reqs,
186 max_model_len=self.max_model_len,
@@ -180,7 +188,7 @@ class GPUModelRunner(LoRAModelRunnerMixin):
188 device=self.device,
189 pin_memory=self.pin_memory,
190 vocab_size=self.model_config.get_vocab_size(),
183 - block_size=self.cache_config.block_size,
191 + block_sizes=[self.cache_config.block_size],
192 )
193
194 self.use_cuda_graph = (self.vllm_config.compilation_config.level
@@ -2040,6 +2048,35 @@ class GPUModelRunner(LoRAModelRunnerMixin):
2048 self.attn_backends.append(attn_backend_i)
2049 self.attn_metadata_builders.append(attn_metadata_builder_i)
2050
2051 + def may_reinitialize_input_batch(self,
2052 + kv_cache_config: KVCacheConfig) -> None:
2053 + """
2054 + Re-initialize the input batch if the block sizes are different from
2055 + `[self.cache_config.block_size]`. This usually happens when there
2056 + are multiple KV cache groups.
2057 +
2058 + Args:
2059 + kv_cache_config: The KV cache configuration.
2060 + """
2061 + block_sizes = [
2062 + kv_cache_group.kv_cache_spec.block_size
2063 + for kv_cache_group in kv_cache_config.kv_cache_groups
2064 + ]
2065 + if block_sizes != [self.cache_config.block_size]:
2066 + assert self.cache_config.cpu_offload_gb == 0, (
2067 + "Cannot re-initialize the input batch when CPU weight "
2068 + "offloading is enabled. See https://github.com/vllm-project/vllm/pull/18298 " # noqa: E501
2069 + "for more details.")
2070 + self.input_batch = InputBatch(
2071 + max_num_reqs=self.max_num_reqs,
2072 + max_model_len=self.max_model_len,
2073 + max_num_batched_tokens=self.max_num_tokens,
2074 + device=self.device,
2075 + pin_memory=self.pin_memory,
2076 + vocab_size=self.model_config.get_vocab_size(),
2077 + block_sizes=block_sizes,
2078 + )
2079 +
2080 def initialize_kv_cache(self, kv_cache_config: KVCacheConfig) -> None:
2081 """
2082 Initialize KV cache based on `kv_cache_config`.
@@ -2047,11 +2084,8 @@ class GPUModelRunner(LoRAModelRunnerMixin):
2084 kv_cache_config: Configuration for the KV cache, including the KV
2085 cache size of each layer
2086 """
2050 - if len(kv_cache_config.kv_cache_groups) > 1:
2051 - raise NotImplementedError(
2052 - "Hybrid models with more than one KV cache type are not "
2053 - "supported yet.")
2087 self.kv_cache_config = kv_cache_config
2088 + self.may_reinitialize_input_batch(kv_cache_config)
2089 self.initialize_attn_backend(kv_cache_config)
2090
2091 kv_caches: dict[str, torch.Tensor] = {}
vllm/v1/worker/tpu_model_runner.py
+4 -3
@@ -200,7 +200,7 @@ class TPUModelRunner(LoRAModelRunnerMixin):
200 device=self.device,
201 pin_memory=self.pin_memory,
202 vocab_size=self.model_config.get_vocab_size(),
203 - block_size=self.block_size,
203 + block_sizes=[self.block_size],
204 )
205
206 # Cached torch/numpy tensor
@@ -1358,8 +1358,9 @@ class TPUModelRunner(LoRAModelRunnerMixin):
1358 device=self.device,
1359 pin_memory=self.pin_memory,
1360 vocab_size=self.model_config.get_vocab_size(),
1361 - block_size=kv_cache_config.kv_cache_groups[0].kv_cache_spec.
1362 - block_size,
1361 + block_sizes=[
1362 + kv_cache_config.kv_cache_groups[0].kv_cache_spec.block_size
1363 + ],
1364 )
1365 # Verify dtype compatibility between block_table_cpu and input_batch
1366 assert self.block_table_cpu.dtype == self.input_batch.block_table[