[https://nvbugs/6395830][fix] Qwen-VL mRoPE: move seq-slot delta cache update to model device#16529
Closed
nv-guomingz wants to merge 1 commit into
Closed
[https://nvbugs/6395830][fix] Qwen-VL mRoPE: move seq-slot delta cache update to model device#16529nv-guomingz wants to merge 1 commit into
nv-guomingz wants to merge 1 commit into
Conversation
Contributor
📝 WalkthroughWalkthroughUpdates Qwen2-VL MRoPE preparation to move concatenated per-request delta tensors to the cache device before indexed copying, supporting CPU-resident delta inputs. ChangesQwen2-VL MRoPE preparation
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
…e update to model device
Text-only startup of the Qwen3.6-27B dense VL checkpoint crashes during
KV-cache capacity estimation in the shared Qwen-VL mRoPE path
(`_prepare_qwen_vl_mrope_config`):
mrope_position_deltas_cache.index_copy_(0, seq_slots, deltas)
RuntimeError: Expected all tensors to be on the same device, but got
source is on cpu, different from other tensors on cuda:0
Root cause: checkpoints carrying `language_model_only: false` with the
dense `Qwen3_5ForConditionalGeneration` arch are routed to
`QwenImageBenchModel`, whose `multimodal_data_device_paths` was missing
the `mrope_config.mrope_position_ids` / `mrope_config.mrope_position_deltas`
entries that its sibling `_Qwen3_5VLModel` lists. The engine's H2D move
(`MultimodalParams.to_device` with `target_keywords`) therefore skips the
mRoPE tensors, leaving the deltas CPU-resident when the GPU seq-slot cache
write (introduced in NVIDIA#11943) consumes them. MoE VL checkpoints
(`Qwen3_5MoeForConditionalGeneration`) never match the image-bench route
and are unaffected.
Fix both layers:
- `QwenImageBenchModel.multimodal_data_device_paths`: add the two
`mrope_config.*` entries, matching `_Qwen3_5VLModel`, so mRoPE tensors
ride the engine's pinned async H2D move like every other Qwen-VL model.
- `_prepare_qwen_vl_mrope_config`: normalize `deltas` onto the cache
device before `index_copy_` as a defensive backstop for any path that
still reaches the write branch with CPU tensors (no-op when devices
already match).
Signed-off-by: nv-guomingz <137257613+nv-guomingz@users.noreply.github.com>
nv-guomingz
force-pushed
the
user/guomingz/fix_nvbug_6395830
branch
from
July 17, 2026 07:47
559b9ad to
425e1a2
Compare
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Background / motivation
Running the Qwen3.6-27B dense VL checkpoint text-only through the PyTorch backend crashes at startup during KV-cache capacity estimation:
Stack (Qwen3.6-27B-NVFP4, tp1, CUTEDSL, text prompt):
Root cause
Checkpoints carrying
language_model_only: falsewith the denseQwen3_5ForConditionalGenerationarchitecture matchis_qwen_image_bench_configand are routed toQwenImageBenchModel. That model'smultimodal_data_device_pathswas missing themrope_config.mrope_position_ids/mrope_config.mrope_position_deltasentries that its sibling_Qwen3_5VLModellists, so the engine's H2D move (MultimodalParams.to_devicewithtarget_keywords) skips the mRoPE tensors. The deltas then reach the GPU seq-slot cache write (introduced in #11943) still CPU-resident, and the device-strictindex_copy_fails.Why other Qwen-VL configs are unaffected:
Qwen3_5MoeForConditionalGeneration, e.g. Qwen3.6-35B-A3B) can never match the image-bench detection (it requires the dense arch), route toQwen3_5MoeVLModelwhose device paths include the mRoPE keys, and run clean — verified on the pre-fix tree with the identical single-GPU command.language_model_only: falseroute toQwen3_5VLModel, which also lists the mRoPE keys.Summary
Two complementary changes:
QwenImageBenchModel.multimodal_data_device_paths: add the twomrope_config.*entries, matching_Qwen3_5VLModel, so mRoPE tensors ride the engine's pinned async H2D move like every other Qwen-VL model (covers real multimodal requests as well as the text-only dummy probe)._prepare_qwen_vl_mrope_config(shared Qwen-VL mRoPE library): normalizedeltasonto the cache device beforeindex_copy_as a defensive backstop for any path that still reaches the write branch with CPU tensors. No-op when devices already match.Impact
.to()is a no-op).deltasis one element per seq slot.Test
--moe_backend CUTEDSL, text prompts: previously crashed inconfigure_kv_cache_capacity; with this PR startup completes and generation produces coherent output.🤖 Generated with Claude Code