Skip to content

Fix: Prevent Runtime Crashes in MiniCPM-V/O Multimodal Inference on CUDA and XPU - #43760

Open
weizhoublue wants to merge 2 commits into
vllm-project:mainfrom
weizhoublue:fix-minicpmv-resampler-device-mismatch
Open

weizhoublue wants to merge 2 commits into
vllm-project:mainfrom
weizhoublue:fix-minicpmv-resampler-device-mismatch

Conversation

@weizhoublue

@weizhoublue weizhoublue commented May 27, 2026

Copy link
Copy Markdown
Contributor

Purpose

Trigger Scenario:
Running MiniCPM-V (2.5/2.6/4.0) or MiniCPM-O (4.5) image/video inference on non-CPU devices (CUDA/XPU) when positional embedding buffers stay on CPU.

Symptom:
PyTorch runtime error: Expected all tensors to be on the same device . Inference fails.

Expected Behavior:
Resampler performs tensor operations on same device, executing image/video inference successfully.

Root Cause:
Positional embedding buffers registered with persistent=False remain on CPU. Original code converted only tensor data type ( .to(dtype) ) without specifying target device, leading to device mismatch (CPU vs CUDA/XPU) during tensor addition.

Test Plan

Test Result


Essential Elements of an Effective PR Description Checklist
  • The purpose of the PR, such as "Fix some issue (link existing issues this PR will resolve)".
  • The test plan, such as providing test command.
  • The test results, such as pasting the results comparison before and after, or e2e results
  • (Optional) The necessary documentation update, such as updating supported_models.md and examples for a new model.

@mergify mergify Bot added nvidia intel-gpu Related to Intel GPU labels May 27, 2026
@mergify

mergify Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

Hi @weizhoublue, the pre-commit checks have failed. Please run:

uv pip install pre-commit>=4.5.1
pre-commit install
pre-commit run --all-files

Then, commit the changes and push to your branch.

For future commits, pre-commit will run automatically on changed files before each commit.

Tip

Is mypy failing?
mypy is run differently in CI. If the failure is related to this check, please use the following command to run it locally:
# For mypy (substitute "3.10" with the failing version if needed)
pre-commit run --hook-stage manual mypy-3.10

Signed-off-by: weizhoublue <weizhou.lan@daocloud.io>
@weizhoublue
weizhoublue force-pushed the fix-minicpmv-resampler-device-mismatch branch from ae01567 to 3789b74 Compare May 27, 2026 07:57
@hclsys

hclsys commented May 27, 2026

Copy link
Copy Markdown
Contributor

This is a clean, complete fix for the device mismatch. I traced both sites:

  • Site 1 (pos_embed, ~L220): device is already the in-scope local used right above for self._adjust_pos_cache(tgt_sizes, device=device) and key_padding_mask = torch.zeros(..., device=device). So .to(device=device, dtype=dtype) moves the CPU-resident self.pos_embed buffer onto the same device the rest of the computation already uses — exactly the mismatch in the traceback. No NameError risk.
  • Site 2 (temporal_pos_embed, ~L377): same — the sibling branch already does torch.zeros(self.embed_dim, dtype=dtype, device=device), so device is valid and correct here too. The bug was that only the else branch's .to(dtype) forgot the device while its if counterpart was already device-correct — nice catch on that asymmetry.

I also grepped the module for other .to(dtype)-only calls on these CPU buffers to check the fix is exhaustive: the only two are the exact lines you patched (L220, L377); the __init__ one at L181 already does .to(device). So there's no sibling latent crash left behind — this fully covers it.

Minimal, surgical, and the device source is provably the right one. LGTM. (Optional: a one-line CUDA/XPU smoke test in CI asserting pos_embed.device == x.device would guard against a future buffer regressing back to CPU, but not blocking.)

Signed-off-by: weizhoublue <weizhou.lan@daocloud.io>
@weizhoublue

Copy link
Copy Markdown
Contributor Author

This is a clean, complete fix for the device mismatch. I traced both sites:

  • Site 1 (pos_embed, ~L220): device is already the in-scope local used right above for self._adjust_pos_cache(tgt_sizes, device=device) and key_padding_mask = torch.zeros(..., device=device). So .to(device=device, dtype=dtype) moves the CPU-resident self.pos_embed buffer onto the same device the rest of the computation already uses — exactly the mismatch in the traceback. No NameError risk.
  • Site 2 (temporal_pos_embed, ~L377): same — the sibling branch already does torch.zeros(self.embed_dim, dtype=dtype, device=device), so device is valid and correct here too. The bug was that only the else branch's .to(dtype) forgot the device while its if counterpart was already device-correct — nice catch on that asymmetry.

I also grepped the module for other .to(dtype)-only calls on these CPU buffers to check the fix is exhaustive: the only two are the exact lines you patched (L220, L377); the __init__ one at L181 already does .to(device). So there's no sibling latent crash left behind — this fully covers it.

Minimal, surgical, and the device source is provably the right one. LGTM. (Optional: a one-line CUDA/XPU smoke test in CI asserting pos_embed.device == x.device would guard against a future buffer regressing back to CPU, but not blocking.)

sure, new unit tests were added

@hclsys

hclsys commented May 27, 2026

Copy link
Copy Markdown
Contributor

nice, tests close the loop. lgtm.

@weizhoublue

weizhoublue commented May 27, 2026

Copy link
Copy Markdown
Contributor Author

btw, failed buildkite/intel-ci jobs ( XPU V1 test and XPU example Test ) are unrelated to this PR.

This PR only edits minicpmv.py and adds test in test_minicpmv_resampler.py. Changes do not modify DeepSeek-V4 files or touch cutlass imports

maybe pr #43790 is trying to fix this CI issue

@github-actions

Copy link
Copy Markdown

This pull request has been automatically marked as stale because it has not had any activity within 90 days. It will be automatically closed if no further activity occurs within 30 days. Leave a comment if you feel this pull request should remain open. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

intel-gpu Related to Intel GPU nvidia stale Over 90 days of inactivity

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants