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 10, 12:45 UTC
[MM Encoder]: Make MMEncoderAttention's `scale` takes effect properly (#31950)
Signed-off-by: Isotr0py <mozf@mail2.sysu.edu.cn>
Isotr0py committed
Jan 8, 2026 at 18:33 UTC
2972a05473d64a21c7390a5676bbb07bd8d2c8da
11 files changed
+32
-8
vllm/attention/layers/mm_encoder_attention.py
+2
@@ -133,6 +133,7 @@ class MMEncoderAttention(CustomOp):
133
q=query,
134
k=key,
135
v=value,
136
+ scale=self.scale,
137
cu_seqlens=cu_seqlens,
138
)
139
if is_reshaped:
@@ -167,6 +168,7 @@ class MMEncoderAttention(CustomOp):
168
q=query,
169
k=key,
170
v=value,
171
+ scale=self.scale,
172
cu_seqlens=cu_seqlens,
173
max_seqlen=max_seqlen,
174
batch_size=bsz,
vllm/attention/ops/vit_attn_wrappers.py
+21
-8
@@ -27,6 +27,7 @@ def flash_attn_maxseqlen_wrapper(
27
batch_size: int,
28
is_rocm_aiter: bool,
29
fa_version: int | None,
30
+ scale: float | None = None,
31
cu_seqlens: torch.Tensor | None = None,
32
max_seqlen: torch.Tensor | None = None,
33
) -> torch.Tensor:
@@ -57,6 +58,7 @@ def flash_attn_maxseqlen_wrapper(
58
max_seqlen_k=max_seqlen,
59
dropout_p=0.0,
60
causal=False,
61
+ softmax_scale=scale,
62
**kwargs,
63
)
64
context_layer = einops.rearrange(output, "(b s) h d -> b s h d", b=batch_size)
@@ -67,11 +69,12 @@ def flash_attn_maxseqlen_wrapper_fake(
69
q: torch.Tensor,
70
k: torch.Tensor,
71
v: torch.Tensor,
70
- cu_seqlens: torch.Tensor,
71
- max_seqlen: torch.Tensor,
72
batch_size: int,
73
is_rocm_aiter: bool,
74
fa_version: int | None,
75
+ scale: float | None,
76
+ cu_seqlens: torch.Tensor | None,
77
+ max_seqlen: torch.Tensor | None,
78
) -> torch.Tensor:
79
return torch.empty_like(q)
80
@@ -90,6 +93,7 @@ def vit_flash_attn_wrapper(
93
batch_size: int,
94
is_rocm_aiter: bool,
95
fa_version: int | None,
96
+ scale: float | None = None,
97
cu_seqlens: torch.Tensor | None = None,
98
max_seqlen: torch.Tensor | None = None,
99
) -> torch.Tensor:
@@ -100,18 +104,24 @@ def vit_flash_attn_wrapper(
104
batch_size,
105
is_rocm_aiter,
106
fa_version,
107
+ scale,
108
cu_seqlens,
109
max_seqlen,
110
)
111
112
108
-def apply_sdpa(q: torch.Tensor, k: torch.Tensor, v: torch.Tensor) -> torch.Tensor:
113
+def apply_sdpa(
114
+ q: torch.Tensor,
115
+ k: torch.Tensor,
116
+ v: torch.Tensor,
117
+ scale: float | None = None,
118
+) -> torch.Tensor:
119
"""
120
Input shape:
121
(batch_size x seq_len x num_heads x head_size)
122
"""
123
q, k, v = (einops.rearrange(x, "b s h d -> b h s d") for x in [q, k, v])
114
- output = F.scaled_dot_product_attention(q, k, v, dropout_p=0.0)
124
+ output = F.scaled_dot_product_attention(q, k, v, dropout_p=0.0, scale=scale)
125
output = einops.rearrange(output, "b h s d -> b s h d ")
126
return output
127
@@ -122,6 +132,7 @@ def torch_sdpa_wrapper(
132
q: torch.Tensor,
133
k: torch.Tensor,
134
v: torch.Tensor,
135
+ scale: float | None = None,
136
cu_seqlens: torch.Tensor | None = None,
137
) -> torch.Tensor:
138
# Never remove the contiguous logic for ROCm
@@ -132,7 +143,7 @@ def torch_sdpa_wrapper(
143
v = v.contiguous()
144
145
if cu_seqlens is None:
135
- return apply_sdpa(q, k, v)
146
+ return apply_sdpa(q, k, v, scale=scale)
147
148
outputs = []
149
@@ -141,7 +152,7 @@ def torch_sdpa_wrapper(
152
k_chunks = torch.split(k, lens, dim=1)
153
v_chunks = torch.split(v, lens, dim=1)
154
for q_i, k_i, v_i in zip(q_chunks, k_chunks, v_chunks):
144
- output_i = apply_sdpa(q_i, k_i, v_i)
155
+ output_i = apply_sdpa(q_i, k_i, v_i, scale=scale)
156
outputs.append(output_i)
157
context_layer = torch.cat(outputs, dim=1)
158
return context_layer
@@ -151,7 +162,8 @@ def torch_sdpa_wrapper_fake(
162
q: torch.Tensor,
163
k: torch.Tensor,
164
v: torch.Tensor,
154
- cu_seqlens: torch.Tensor,
165
+ scale: float | None,
166
+ cu_seqlens: torch.Tensor | None,
167
) -> torch.Tensor:
168
return torch.empty_like(q)
169
@@ -167,6 +179,7 @@ def vit_torch_sdpa_wrapper(
179
q: torch.Tensor,
180
k: torch.Tensor,
181
v: torch.Tensor,
182
+ scale: float | None = None,
183
cu_seqlens: torch.Tensor | None = None,
184
) -> torch.Tensor:
172
- return torch.ops.vllm.torch_sdpa_wrapper(q, k, v, cu_seqlens)
185
+ return torch.ops.vllm.torch_sdpa_wrapper(q, k, v, scale, cu_seqlens)
vllm/model_executor/models/dots_ocr.py
+1
@@ -271,6 +271,7 @@ class DotsVisionAttention(nn.Module):
271
self.attn = MMEncoderAttention(
272
num_heads=self.num_attention_heads_per_partition,
273
head_size=self.hidden_size_per_attention_head,
274
+ scale=self.hidden_size_per_attention_head**-0.5,
275
multimodal_config=multimodal_config,
276
prefix=f"{prefix}.attn",
277
)
vllm/model_executor/models/ernie45_vl.py
+1
@@ -152,6 +152,7 @@ class Ernie4_5_VisionAttention(nn.Module):
152
self.attn = MMEncoderAttention(
153
num_heads=self.num_attention_heads_per_partition,
154
head_size=self.hidden_size_per_attention_head,
155
+ scale=self.hidden_size_per_attention_head**-0.5,
156
multimodal_config=multimodal_config,
157
prefix=f"{prefix}.attn",
158
)
vllm/model_executor/models/glm4_1v.py
+1
@@ -304,6 +304,7 @@ class Glm4vVisionAttention(nn.Module):
304
self.attn = MMEncoderAttention(
305
num_heads=self.num_attention_heads_per_partition,
306
head_size=self.hidden_size_per_attention_head,
307
+ scale=self.hidden_size_per_attention_head**-0.5,
308
multimodal_config=multimodal_config,
309
)
310
vllm/model_executor/models/glmasr.py
+1
@@ -188,6 +188,7 @@ class GlmAsrEncoderAttention(nn.Module):
188
self.attn = MMEncoderAttention(
189
num_heads=self.num_heads_per_rank,
190
head_size=self.head_dim,
191
+ scale=self.head_dim**-0.5,
192
num_kv_heads=self.num_kv_heads_per_rank,
193
prefix=f"{prefix}.attn",
194
)
vllm/model_executor/models/isaac.py
+1
@@ -984,6 +984,7 @@ class Siglip2VisionAttention(nn.Module):
984
self.attn = MMEncoderAttention(
985
num_heads=self.num_attention_heads_per_partition,
986
head_size=self.hidden_size_per_attention_head,
987
+ scale=self.hidden_size_per_attention_head**-0.5,
988
prefix=f"{prefix}.attn",
989
multimodal_config=multimodal_config,
990
)
vllm/model_executor/models/moonvit.py
+1
@@ -390,6 +390,7 @@ class MoonVitEncoderLayer(nn.Module):
390
self.attn = MMEncoderAttention(
391
num_heads=self.num_attention_heads_per_partition,
392
head_size=self.hidden_size_per_attention_head,
393
+ scale=self.hidden_size_per_attention_head**-0.5,
394
multimodal_config=multimodal_config,
395
prefix=f"{prefix}.attn",
396
)
vllm/model_executor/models/paddleocr_vl.py
+1
@@ -564,6 +564,7 @@ class SiglipAttention(nn.Module):
564
self.attn = MMEncoderAttention(
565
num_heads=self.num_attention_heads_per_partition,
566
head_size=self.hidden_size_per_attention_head,
567
+ scale=self.hidden_size_per_attention_head**-0.5,
568
multimodal_config=multimodal_config,
569
prefix=f"{prefix}.attn",
570
)
vllm/model_executor/models/qwen2_5_vl.py
+1
@@ -352,6 +352,7 @@ class Qwen2_5_VisionAttention(nn.Module):
352
self.attn = MMEncoderAttention(
353
num_heads=self.num_attention_heads_per_partition,
354
head_size=self.hidden_size_per_attention_head,
355
+ scale=self.hidden_size_per_attention_head**-0.5,
356
multimodal_config=multimodal_config,
357
)
358
vllm/model_executor/models/qwen2_vl.py
+1
@@ -327,6 +327,7 @@ class Qwen2VisionAttention(nn.Module):
327
self.attn = MMEncoderAttention(
328
num_heads=self.num_attention_heads_per_partition,
329
head_size=self.hidden_size_per_attention_head,
330
+ scale=self.hidden_size_per_attention_head**-0.5,
331
multimodal_config=multimodal_config,
332
)
333