[Bugfix] Fix multi-modal support on CPU MRV2 (#50073)

Signed-off-by: jiang1.li <jiang1.li@intel.com>

Li, Jiang committed Jul 28, 2026 at 14:09 UTC 90245f4190a35593a625e4bc349485c39c774d39
3 files changed +18 -1
vllm/multimodal/inputs.py
+2
@@ -457,6 +457,8 @@ class BaseMultiModalField(ABC):
457 device = "cpu"
458 if pin_memory and self.keep_on_cpu:
459 pin_memory = False
460 + if device == "cpu" or device == torch.device("cpu"):
461 + pin_memory = False
462
463 batch = [elem.data for elem in elems]
464 out = self._reduce_data(batch, pin_memory=pin_memory)
vllm/v1/worker/cpu/shm.py
+12
@@ -24,12 +24,17 @@ def fake_pin_memory(self: torch.Tensor, *args: Any, **kwargs: Any) -> torch.Tens
24 class _EventPlaceholder:
25 def __init__(self, *args, **kwargs) -> None:
26 self.record = noop
27 + self.wait = noop
28 self.synchronize = noop
29
30
31 class _StreamPlaceholder:
32 def __init__(self, *args, **kwargs) -> None:
33 self.wait_stream = noop
34 + self.wait_event = noop
35 + self.record_event = noop
36 + self.synchronize = noop
37 + self.query = lambda: True
38 self.device = torch.device("cpu")
39
40 def __enter__(self, *args, **kwargs):
@@ -55,6 +60,7 @@ torch.cuda.current_stream = lambda *args, **kwargs: _StreamPlaceholder()
60 torch.accelerator.synchronize = noop
61 torch.accelerator.empty_cache = noop
62 torch.Tensor.pin_memory = fake_pin_memory
63 +torch.Tensor.record_stream = noop
64 torch.accelerator.get_memory_info = get_memory_info
65
66 # Patch vLLM torch utils
@@ -80,3 +86,9 @@ import vllm.v1.worker.gpu.buffer_utils as gpu_buffer_utils
86 import vllm.v1.worker.cpu.buffer_utils as cpu_buffer_utils
87
88 gpu_buffer_utils.UvaBuffer = cpu_buffer_utils.UvaBuffer
89 +
90 +# Patch Triton
91 +from vllm.triton_utils import HAS_TRITON, tl
92 +
93 +if HAS_TRITON:
94 + tl.debug_barrier = noop
vllm/v1/worker/gpu/model_states/encoder_decoder.py
+4 -1
@@ -9,6 +9,7 @@ import torch.nn as nn
9
10 from vllm.config import VllmConfig
11 from vllm.config.compilation import CUDAGraphMode
12 +from vllm.utils.torch_utils import PIN_MEMORY
13 from vllm.v1.kv_cache_interface import CrossAttentionSpec, KVCacheConfig
14 from vllm.v1.worker.gpu.attn_utils import build_attn_metadata
15 from vllm.v1.worker.gpu.input_batch import InputBatch
@@ -157,7 +158,9 @@ class EncoderDecoderModelState(ModelState):
158 for_capture: bool,
159 num_reqs: int,
160 ) -> dict[int, tuple[torch.Tensor, np.ndarray]]:
160 - encoder_seq_lens = torch.zeros(num_reqs, dtype=torch.int32, pin_memory=True)
161 + encoder_seq_lens = torch.zeros(
162 + num_reqs, dtype=torch.int32, pin_memory=PIN_MEMORY
163 + )
164 encoder_seq_lens_np = encoder_seq_lens.numpy()
165 if not for_capture:
166 # During normal execution, use actual encoder lengths.