@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / 139d155781
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 14, 05:30 UTC

[Frontend] Use engine argument to control MM cache size (#22441)

Signed-off-by: DarkLight1337 <tlleungac@connect.ust.hk>

Cyrus Leung committed Aug 8, 2025 at 00:47 UTC 139d155781c187b6d38ac6d84a516c97ff66bb1f
13 files changed +101 -47
docs/configuration/conserving_memory.md
+1 -1
@@ -86,7 +86,7 @@ llm = LLM(model="meta-llama/Llama-3.1-8B-Instruct",
86
87 If you run out of CPU RAM, try the following options:
88
89 -- (Multi-modal models only) you can set the size of multi-modal processor cache using `VLLM_MM_INPUT_CACHE_GIB` environment variable (default 4 GiB per API process + 4 GiB per engine core process)
89 +- (Multi-modal models only) you can set the size of multi-modal processor cache by setting `mm_processor_cache_gb` engine argument (default 4 GiB per API process + 4 GiB per engine core process)
90 - (CPU backend only) you can set the size of KV cache using `VLLM_CPU_KVCACHE_SPACE` environment variable (default 4 GiB).
91
92 ## Multi-modal input limits
docs/configuration/optimization.md
+9 -3
@@ -161,12 +161,18 @@ By default, the multi-modal processor cache is enabled to avoid repeatedly proce
161 the same multi-modal inputs via Hugging Face `AutoProcessor`,
162 which commonly occurs in multi-turn conversations.
163
164 -You can adjust the size of the cache via `VLLM_MM_INPUT_CACHE_GIB` environment variable
164 +You can adjust the size of the cache by setting the value of `mm_processor_cache_gb`
165 (default 4 GiB per API process + 4 GiB per engine core process).
166 +If you do not benefit much from the cache, you can disable it completely via `mm_processor_cache_gb=0`.
167
167 -If you do not benefit much from the cache, you can disable it completely via `disable_mm_preprocessor_cache`:
168 +Examples:
169
170 ```python
171 +# Use a larger cache
172 llm = LLM(model="Qwen/Qwen2.5-VL-3B-Instruct",
171 - disable_mm_preprocessor_cache=True)
173 + mm_processor_cache_gb=8)
174 +
175 +# Disable the cache
176 +llm = LLM(model="Qwen/Qwen2.5-VL-3B-Instruct",
177 + mm_processor_cache_gb=0)
178 ```
examples/offline_inference/mistral-small.py
+3 -3
@@ -68,7 +68,7 @@ def run_simple_demo(args: argparse.Namespace):
68 max_model_len=4096,
69 max_num_seqs=2,
70 tensor_parallel_size=2,
71 - disable_mm_preprocessor_cache=args.disable_mm_preprocessor_cache,
71 + mm_processor_cache_gb=0 if args.disable_mm_processor_cache else 4,
72 )
73
74 prompt = "Describe this image in one sentence."
@@ -105,7 +105,7 @@ def run_advanced_demo(args: argparse.Namespace):
105 limit_mm_per_prompt={"image": max_img_per_msg},
106 max_model_len=max_img_per_msg * max_tokens_per_img,
107 tensor_parallel_size=2,
108 - disable_mm_preprocessor_cache=args.disable_mm_preprocessor_cache,
108 + mm_processor_cache_gb=0 if args.disable_mm_processor_cache else 4,
109 )
110
111 prompt = "Describe the following image."
@@ -164,7 +164,7 @@ def parse_args():
164 )
165
166 parser.add_argument(
167 - "--disable-mm-preprocessor-cache",
167 + "--disable-mm-processor-cache",
168 action="store_true",
169 help="If True, disables caching of multi-modal processor.",
170 )
examples/offline_inference/vision_language.py
+2 -2
@@ -1563,7 +1563,7 @@ def parse_args():
1563 )
1564
1565 parser.add_argument(
1566 - "--disable-mm-preprocessor-cache",
1566 + "--disable-mm-processor-cache",
1567 action="store_true",
1568 help="If True, disables caching of multi-modal processor.",
1569 )
@@ -1603,7 +1603,7 @@ def main(args):
1603
1604 engine_args = asdict(req_data.engine_args) | {
1605 "seed": args.seed,
1606 - "disable_mm_preprocessor_cache": args.disable_mm_preprocessor_cache,
1606 + "mm_processor_cache_gb": 0 if args.disable_mm_processor_cache else 4,
1607 }
1608 llm = LLM(**engine_args)
1609
tests/models/multimodal/generation/vlm_utils/core.py
+1 -3
@@ -62,9 +62,7 @@ def run_test(
62 # if we run HF first, the cuda initialization will be done and it
63 # will hurt multiprocessing backend with fork method (the default method).
64
65 - vllm_runner_kwargs_: dict[str, Any] = {
66 - "disable_mm_preprocessor_cache": True,
67 - }
65 + vllm_runner_kwargs_: dict[str, Any] = {"mm_processor_cache_gb": 0}
66 if model_info.tokenizer:
67 vllm_runner_kwargs_["tokenizer_name"] = model_info.tokenizer
68 if model_info.tokenizer_mode:
tests/models/multimodal/processing/test_llama4.py
+3 -3
@@ -15,14 +15,14 @@ from ...utils import build_model_context
15 ["meta-llama/Llama-4-Scout-17B-16E-Instruct"])
16 @pytest.mark.parametrize("mm_processor_kwargs", [{}])
17 @pytest.mark.parametrize("num_imgs", [1, 5])
18 -@pytest.mark.parametrize("disable_mm_preprocessor_cache", [True, False])
18 +@pytest.mark.parametrize("mm_processor_cache_gb", [0, 4])
19 @pytest.mark.parametrize("tokenized_prompt", [True, False])
20 def test_processor_override(
21 image_assets: ImageTestAssets,
22 model_id: str,
23 mm_processor_kwargs: dict,
24 num_imgs: int,
25 - disable_mm_preprocessor_cache: bool,
25 + mm_processor_cache_gb: int,
26 tokenized_prompt: bool,
27 ):
28 """Ensure llama4 processor works properly."""
@@ -30,7 +30,7 @@ def test_processor_override(
30 model_id,
31 mm_processor_kwargs=mm_processor_kwargs,
32 limit_mm_per_prompt={"image": num_imgs},
33 - disable_mm_preprocessor_cache=disable_mm_preprocessor_cache,
33 + mm_processor_cache_gb=mm_processor_cache_gb,
34 )
35 processor = MULTIMODAL_REGISTRY.create_processor(ctx.model_config)
36 config = processor.info.get_hf_config()
tests/models/utils.py
+2 -2
@@ -261,7 +261,7 @@ def build_model_context(
261 model_config_kwargs: Optional[dict[str, Any]] = None,
262 mm_processor_kwargs: Optional[dict[str, Any]] = None,
263 limit_mm_per_prompt: Optional[dict[str, int]] = None,
264 - disable_mm_preprocessor_cache: bool = True,
264 + mm_processor_cache_gb: int = 0,
265 ):
266 """Creates an InputContext for a given model.
267
@@ -291,7 +291,7 @@ def build_model_context(
291 seed=0,
292 mm_processor_kwargs=mm_processor_kwargs,
293 limit_mm_per_prompt=limit_mm_per_prompt,
294 - disable_mm_preprocessor_cache=disable_mm_preprocessor_cache,
294 + mm_processor_cache_gb=mm_processor_cache_gb,
295 hf_overrides=model_info.hf_overrides,
296 **model_config_kwargs,
297 )
vllm/config.py
+32 -11
@@ -443,8 +443,15 @@ class ModelConfig:
443 from `AutoProcessor.from_pretrained`. The available overrides depend on the
444 model that is being run. For example, for Phi-3-Vision: `{"num_crops": 4}`.
445 """
446 - disable_mm_preprocessor_cache: bool = False
447 - """If `True`, disable caching of the multi-modal processor."""
446 + mm_processor_cache_gb: int = 4
447 + """The size (in GiB) of the multi-modal processor cache, which is used to
448 + avoid re-processing past multi-modal inputs.
449 +
450 + This cache is duplicated for each API process and engine core process,
451 + resulting in a total memory usage of
452 + `mm_processor_cache_gb * (api_server_count + data_parallel_size)`.
453 +
454 + Set to `0` to disable this cache completely (not recommended)."""
455 override_neuron_config: dict[str, Any] = field(default_factory=dict)
456 """Initialize non-default neuron config or override default neuron config
457 that are specific to Neuron devices, this argument will be used to
@@ -881,17 +888,16 @@ class ModelConfig:
888 limit_per_prompt=self.limit_mm_per_prompt,
889 media_io_kwargs=self.media_io_kwargs,
890 mm_processor_kwargs=self.mm_processor_kwargs,
884 - disable_mm_preprocessor_cache=self.
885 - disable_mm_preprocessor_cache,
891 + mm_processor_cache_gb=self.mm_processor_cache_gb,
892 interleave_mm_strings=self.interleave_mm_strings)
893
894 return None
895
890 - def set_disable_mm_preprocessor_cache(self, value: bool) -> None:
896 + def set_mm_processor_cache_gb(self, value: int) -> None:
897 mm_config = self.get_multimodal_config()
898
893 - self.disable_mm_preprocessor_cache = value
894 - mm_config.disable_mm_preprocessor_cache = value
899 + self.mm_processor_cache_gb = value
900 + mm_config.mm_processor_cache_gb = value
901
902 def _get_encoder_config(self):
903 return get_sentence_transformer_tokenizer_config(
@@ -1698,7 +1704,16 @@ class ModelConfig:
1704 if mm_config is None:
1705 return False
1706
1701 - return not mm_config.disable_mm_preprocessor_cache
1707 + return mm_config.mm_processor_cache_gb > 0
1708 +
1709 + @property
1710 + def enable_mm_processor_cache(self) -> bool:
1711 + """Whether the multi-modal processor cache should be enabled."""
1712 + mm_config = self.multimodal_config
1713 + if mm_config is None:
1714 + return False
1715 +
1716 + return mm_config.mm_processor_cache_gb > 0
1717
1718 @property
1719 def enable_mm_input_cache(self) -> bool:
@@ -1707,7 +1722,7 @@ class ModelConfig:
1722 if mm_config is None:
1723 return False
1724
1710 - return not mm_config.disable_mm_preprocessor_cache
1725 + return mm_config.mm_processor_cache_gb > 0
1726
1727 def get_mm_input_cache_gb(self) -> int:
1728 mm_config = self.multimodal_config
@@ -3391,9 +3406,15 @@ class MultiModalConfig:
3406 `{"num_crops": 4}`.
3407 """
3408
3394 - disable_mm_preprocessor_cache: bool = False
3409 + mm_processor_cache_gb: int = 4
3410 """
3396 - If `True`, disable caching of the multi-modal processor.
3411 + The size (in GiB) of the multi-modal processor cache, which is used to
3412 +
3413 + This cache is duplicated for each API process and engine core process,
3414 + resulting in a total memory usage of
3415 + `mm_processor_cache_gb * (api_server_count + data_parallel_size)`.
3416 +
3417 + Set to `0` to disable this cache completely (not recommended).
3418 """
3419
3420 interleave_mm_strings: bool = False
vllm/engine/arg_utils.py
+27 -7
@@ -358,8 +358,8 @@ class EngineArgs:
358 "media_io_kwargs")
359 mm_processor_kwargs: Optional[Dict[str, Any]] = \
360 MultiModalConfig.mm_processor_kwargs
361 - disable_mm_preprocessor_cache: bool = \
362 - MultiModalConfig.disable_mm_preprocessor_cache
361 + disable_mm_preprocessor_cache: bool = False # DEPRECATED
362 + mm_processor_cache_gb: int = MultiModalConfig.mm_processor_cache_gb
363 # LoRA fields
364 enable_lora: bool = False
365 enable_lora_bias: bool = LoRAConfig.bias_enabled
@@ -720,8 +720,11 @@ class EngineArgs:
720 "--mm-processor-kwargs",
721 **multimodal_kwargs["mm_processor_kwargs"])
722 multimodal_group.add_argument(
723 - "--disable-mm-preprocessor-cache",
724 - **multimodal_kwargs["disable_mm_preprocessor_cache"])
723 + "--mm-processor-cache-gb",
724 + **multimodal_kwargs["mm_processor_cache_gb"])
725 + multimodal_group.add_argument("--disable-mm-preprocessor-cache",
726 + type=bool,
727 + deprecated=True)
728 multimodal_group.add_argument(
729 "--interleave-mm-strings",
730 **multimodal_kwargs["interleave_mm_strings"])
@@ -886,6 +889,23 @@ class EngineArgs:
889 self.model = f"{MODEL_WEIGHTS_S3_BUCKET}/{self.model}"
890 self.load_format = "runai_streamer"
891
892 + if self.disable_mm_preprocessor_cache:
893 + logger.warning(
894 + "`--disable-mm-preprocessor-cache` is deprecated "
895 + "and will be removed in v0.13. "
896 + "Please use `--mm-processor-cache-gb 0` instead.", )
897 +
898 + self.mm_processor_cache_gb = 0
899 + elif envs.VLLM_MM_INPUT_CACHE_GIB != 4:
900 + logger.warning(
901 + "VLLM_MM_INPUT_CACHE_GIB` is deprecated "
902 + "and will be removed in v0.13. "
903 + "Please use `--mm-processor-cache-gb %d` instead.",
904 + envs.VLLM_MM_INPUT_CACHE_GIB,
905 + )
906 +
907 + self.mm_processor_cache_gb = envs.VLLM_MM_INPUT_CACHE_GIB
908 +
909 return ModelConfig(
910 model=self.model,
911 hf_config_path=self.hf_config_path,
@@ -922,7 +942,7 @@ class EngineArgs:
942 use_async_output_proc=not self.disable_async_output_proc,
943 config_format=self.config_format,
944 mm_processor_kwargs=self.mm_processor_kwargs,
925 - disable_mm_preprocessor_cache=self.disable_mm_preprocessor_cache,
945 + mm_processor_cache_gb=self.mm_processor_cache_gb,
946 override_neuron_config=self.override_neuron_config,
947 override_pooler_config=self.override_pooler_config,
948 logits_processor_pattern=self.logits_processor_pattern,
@@ -1234,13 +1254,13 @@ class EngineArgs:
1254 dp_supports_mm_processor_cache = (self.data_parallel_size == 1
1255 or data_parallel_external_lb)
1256 if (not dp_supports_mm_processor_cache
1237 - and not model_config.disable_mm_preprocessor_cache):
1257 + and model_config.mm_processor_cache_gb > 0):
1258 logger.warning(
1259 "Multi-modal processor cache is disabled because "
1260 "it is not compatible with data parallelism when "
1261 "there does not exist a one-to-one correspondance "
1262 "between API and engine core processes.")
1243 - model_config.set_disable_mm_preprocessor_cache(True)
1263 + model_config.set_mm_processor_cache_gb(0)
1264
1265 speculative_config = self.create_speculative_config(
1266 target_model_config=model_config,
vllm/entrypoints/cli/serve.py
+3 -4
@@ -138,13 +138,13 @@ def run_multi_api_server(args: argparse.Namespace):
138 num_api_servers = args.api_server_count
139 assert num_api_servers > 0
140
141 - orig_disable_mm_preprocessor_cache = args.disable_mm_preprocessor_cache
141 + orig_mm_processor_cache_gb = args.mm_processor_cache_gb
142
143 if num_api_servers > 1:
144 setup_multiprocess_prometheus()
145
146 # Not compatible with API server scale-out
147 - args.disable_mm_preprocessor_cache = True
147 + args.mm_processor_cache_gb = 0
148
149 listen_address, sock = setup_server(args)
150
@@ -161,8 +161,7 @@ def run_multi_api_server(args: argparse.Namespace):
161 raise ValueError("VLLM_ALLOW_RUNTIME_LORA_UPDATING cannot be used "
162 "with api_server_count > 1")
163
164 - if model_config.is_multimodal_model and not (
165 - orig_disable_mm_preprocessor_cache):
164 + if model_config.is_multimodal_model and orig_mm_processor_cache_gb > 0:
165 logger.warning("Multi-modal processor cache is disabled because "
166 "it is not compatible with `api_server_count > 1`.")
167
vllm/envs.py
+1 -1
@@ -561,7 +561,7 @@ environment_variables: dict[str, Callable[[], Any]] = {
561 "VLLM_VIDEO_LOADER_BACKEND":
562 lambda: os.getenv("VLLM_VIDEO_LOADER_BACKEND", "opencv"),
563
564 - # Cache size (in GiB per process) for multimodal input cache
564 + # [DEPRECATED] Cache size (in GiB per process) for multimodal input cache
565 # Default is 4 GiB per API process + 4 GiB per engine core process
566 "VLLM_MM_INPUT_CACHE_GIB":
567 lambda: int(os.getenv("VLLM_MM_INPUT_CACHE_GIB", "4")),
vllm/multimodal/registry.py
+16 -6
@@ -6,7 +6,6 @@ from typing import TYPE_CHECKING, Generic, Optional, Protocol, TypeVar
6
7 import torch.nn as nn
8
9 -from vllm.envs import VLLM_MM_INPUT_CACHE_GIB
9 from vllm.inputs import InputProcessingContext
10 from vllm.logger import init_logger
11 from vllm.transformers_utils.tokenizer import (AnyTokenizer,
@@ -96,11 +95,22 @@ class MultiModalRegistry:
95 self._processor_factories = ClassRegistry[nn.Module,
96 _ProcessorFactories]()
97
99 - self._processing_cache = ProcessingCache(VLLM_MM_INPUT_CACHE_GIB)
98 + self._processor_cache: Optional[ProcessingCache] = None
99 +
100 + def _get_processor_cache(self, model_config: "ModelConfig"):
101 + capacity_gb = model_config.mm_processor_cache_gb
102 + if capacity_gb is None:
103 + return None # Overrides `disable_cache` argument
104 +
105 + if self._processor_cache is None:
106 + self._processor_cache = ProcessingCache(capacity_gb)
107 +
108 + return self._processor_cache
109
110 def reset_processor_cache(self) -> bool:
111 """Reset the multi-modal processing cache."""
103 - self._processing_cache.reset()
112 + if self._processor_cache:
113 + self._processor_cache.reset()
114
115 return True # Success
116
@@ -244,14 +254,14 @@ class MultiModalRegistry:
254 if tokenizer is None and not model_config.skip_tokenizer_init:
255 tokenizer = cached_tokenizer_from_config(model_config)
256 if disable_cache is None:
247 - mm_config = model_config.get_multimodal_config()
248 - disable_cache = mm_config.disable_mm_preprocessor_cache
257 + disable_cache = not model_config.enable_mm_processor_cache
258
259 model_cls = self._get_model_cls(model_config)
260 factories = self._processor_factories[model_cls]
261
262 ctx = InputProcessingContext(model_config, tokenizer)
254 - cache = None if disable_cache else self._processing_cache
263 + cache = None if disable_cache else self._get_processor_cache(
264 + model_config)
265
266 return factories.build_processor(ctx, cache=cache)
267
vllm/v1/core/kv_cache_utils.py
+1 -1
@@ -430,7 +430,7 @@ def _gen_mm_extra_hash_keys(request: Request, start_token_idx: int,
430 raise ValueError(
431 "The number of multi-modal positions and hashes must match. This "
432 "is likely because you did not enable MM hashing. "
433 - "Please set `disable_mm_preprocessor_cache=False`.")
433 + "Please set `mm_processor_cache_gb > 0`.")
434
435 # Note that we assume mm_positions is sorted by offset.
436 # We do not need to check all mm inputs if the start token index is out of