Repository navigation
[ROCm][RDNA][Perf] Fix MiniCPM-V TTFT regression from always-on ViT attention mask - #1398
Merged
stoivonen-amd merged 1 commit intoOct 28, 2026
Conversation
stoivonen-amd
force-pushed
the
stephant/idefics2-skip-encoder-mask-when-unpadded
branch
from
October 26, 2026 18:33
b207642 to
1729809
Compare
stoivonen-amd
marked this pull request as ready for review
October 26, 2026 18:48
mgehre-amd
approved these changes
Oct 27, 2026
mgehre-amd
reviewed
Oct 27, 2026
…ttention mask Skip the ViT attention mask in the eager MiniCPM-V encoder path when no slice is padded. vllm-project#42785 removed the equivalent check from Idefics2VisionTransformer.forward, adding ~8-9 ms of TTFT to small MiniCPM-V models on gfx1151. HF NaViT SigLIP skips the mask in the same case. Cause: since vllm-project#42785 (encoder CUDA graph for MiniCPM-V) a mask is built for every request. Any mask takes MMEncoderAttention off its fused backend (e.g. --mm-encoder-attn-backend TRITON_ATTN) and onto torch SDPA with a padded additive mask (27 SDPA + 27 constant_pad_nd calls per request for the So400m tower). Fix: the eager get_vision_hidden_states of MiniCPM-V 2.5/2.6/4.0/4.5 now share _mcpmv_patch_attention_mask, which returns None when every slice has the same patch count. tgt_sizes is kept on CPU, so the check needs no device sync, and the shared Idefics2 encoder is unchanged. The encoder CUDA graph path still always passes the mask. Padded batches still get the mask. Impact on gfx1151: TTFT of the Internal MiniCPM 0.9B/4B resized VLM rows regressed by ~8-9 ms (e.g. 0.9B BF16: 59.8 -> 69.0 ms, +15%), independent of LLM size; decode is unchanged. With this change, 0.9B BF16 on the same wheel goes from 72.4 to 64.1 ms (3 runs each). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Stephan Toivonen <Stephan.Toivonen@amd.com>
stoivonen-amd
force-pushed
the
stephant/idefics2-skip-encoder-mask-when-unpadded
branch
from
October 27, 2026 15:57
1729809 to
673ce84
Compare
roberteg16
approved these changes
Oct 28, 2026
stoivonen-amd
deleted the
stephant/idefics2-skip-encoder-mask-when-unpadded
branch
October 28, 2026 14:33
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.
Summary
Fixes a ~8–9 ms TTFT regression for MiniCPM-V on gfx1151 (+8–15% on the 0.9B/4B models).
vllm-project#42785 removed the check in
Idefics2VisionTransformer.forwardthat skipped the ViT attention mask when no patch is padded. This PR restores that behavior in the MiniCPM-V caller, matching HF NaViT SigLIP, which skips the mask in the same case. The shared Idefics2 encoder is unchanged.Details
Cause. Any mask forces
MMEncoderAttentionoff its fused backend (e.g.TRITON_ATTN) onto SDPA with padding. With the SigLIP-So400m encoder, an eager profile shows 27× SDPA + 27×constant_pad_ndper request instead of 27×triton_attn_wrapperbefore vllm#42785.Fix. The eager
get_vision_hidden_statesof MiniCPM-V 2.5 / 2.6 / 4.0 / 4.5 now share_mcpmv_patch_attention_mask. It returnsNonewhen every slice has the same patch count, so the encoder skips the attention mask.tgt_sizesis kept on CPU, so the check needs no device sync. Padded batches still get the mask.CUDA graphs. The encoder CUDA graph path (
encoder_cudagraph_forward) is untouched and always passes the mask, so the captured graph is unchanged.Test
gfx1151 (ROCm), BF16,
--mm-encoder-attn-backend TRITON_ATTN, greedy decoding. Models: MiniCPM-V with the SigLIP-So400m encoder (internal 0.9B / 4B checkpoints,openbmb/MiniCPM-V-2_6). Measured by applying this diff to a recent nightly ROCm wheel (dd50dea38).Performance (0.9B, one 560x315 image, 3 runs each, run back to back)
In an earlier session on the same board, a wheel from before vllm#42785 measured 63.4 ms against 69.5 ms for the nightly, so this PR recovers the full regression. Decode is unchanged at ~224 tok/s.
Correctness (greedy tokens vs the nightly, MiniCPM-V-2.6 and 4B)
main, graph and eager runs already diverge by a similar amount.Not run:
test_vit_cudagraph.py -k minicpmv. It only asserts non-empty output, which the graph-mode token comparison above already covers more strictly.Notes
Essential Elements of an Effective PR Description Checklist
supported_models.mdandexamplesfor a new model.🤖 Generated with Claude Code