Skip to content

Commit 64c082d

Browse files
sywangyikalyank007
authored andcommitted
Enable fusedsdpa kernel for vision part of mllama (huggingface#1531)
Signed-off-by: Wang, Yi A <yi.a.wang@intel.com>
1 parent 51e0316 commit 64c082d

4 files changed

Lines changed: 178 additions & 0 deletions

File tree

optimum/habana/transformers/modeling_utils.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@
9090
GaudiMllamaTextCrossAttention,
9191
GaudiMllamaTextModel,
9292
GaudiMllamaTextSelfAttention,
93+
GaudiMllamaVisionEncoder,
94+
GaudiMllamaVisionEncoderLayer,
9395
GaudiMllamaVisionModel,
96+
GaudiMllamaVisionSdpaAttention,
9497
GaudiMptAttention,
9598
GaudiMptBlock,
9699
GaudiMptForCausalLM,
@@ -635,6 +638,9 @@ def adapt_transformers_to_gaudi():
635638
transformers.models.mllama.modeling_mllama.MllamaForConditionalGeneration = GaudiMllamaForConditionalGeneration
636639
transformers.models.mllama.modeling_mllama.MllamaTextModel = GaudiMllamaTextModel
637640
transformers.models.mllama.modeling_mllama.MllamaVisionModel = GaudiMllamaVisionModel
641+
transformers.models.mllama.modeling_mllama.MllamaVisionEncoder = GaudiMllamaVisionEncoder
642+
transformers.models.mllama.modeling_mllama.MllamaVisionEncoderLayer = GaudiMllamaVisionEncoderLayer
643+
transformers.models.mllama.modeling_mllama.MllamaVisionSdpaAttention = GaudiMllamaVisionSdpaAttention
638644

639645
transformers.AutoConfig.register("deci", DeciLMConfig)
640646
transformers.AutoModelForCausalLM.register(DeciLMConfig, DeciLMForCausalLM)

optimum/habana/transformers/models/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,10 @@
147147
GaudiMllamaTextCrossAttention,
148148
GaudiMllamaTextModel,
149149
GaudiMllamaTextSelfAttention,
150+
GaudiMllamaVisionEncoder,
151+
GaudiMllamaVisionEncoderLayer,
150152
GaudiMllamaVisionModel,
153+
GaudiMllamaVisionSdpaAttention,
151154
)
152155
from .modeling_all_models import (
153156
gaudi_check_and_enable_sdpa,

optimum/habana/transformers/models/mllama/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,8 @@
66
GaudiMllamaTextCrossAttention,
77
GaudiMllamaTextModel,
88
GaudiMllamaTextSelfAttention,
9+
GaudiMllamaVisionEncoder,
10+
GaudiMllamaVisionEncoderLayer,
911
GaudiMllamaVisionModel,
12+
GaudiMllamaVisionSdpaAttention,
1013
)

optimum/habana/transformers/models/mllama/modeling_mllama.py

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import os
1919
from typing import List, Optional, Tuple, Union
2020

21+
import habana_frameworks.torch.core as htcore
2122
import torch
2223
import torch.nn.functional as F
2324
import torch.utils.checkpoint
@@ -35,6 +36,10 @@
3536
MllamaTextCrossAttention,
3637
MllamaTextModel,
3738
MllamaTextSelfAttention,
39+
MllamaVisionAttention,
40+
MllamaVisionConfig,
41+
MllamaVisionEncoder,
42+
MllamaVisionEncoderLayer,
3843
MllamaVisionModel,
3944
_prepare_4d_causal_attention_mask_with_cache_position,
4045
_prepare_aspect_ratio_attention_mask,
@@ -107,6 +112,163 @@ def _prepare_cross_attention_mask(
107112
return cross_attention_mask, full_text_row_masked_out_mask
108113

109114

115+
class GaudiMllamaVisionSdpaAttention(MllamaVisionAttention):
116+
def __init__(self, config: MllamaVisionConfig):
117+
super().__init__(config)
118+
self.fused_scaled_dot_product_attention = ModuleFusedSDPA(FusedSDPA) if FusedSDPA else None
119+
120+
# Adapted from MllamaVisionAttention
121+
def forward(
122+
self,
123+
hidden_state: torch.Tensor,
124+
attention_mask: Optional[torch.Tensor] = None,
125+
output_attentions: bool = None,
126+
use_flash_attention: Optional[bool] = False,
127+
) -> torch.Tensor:
128+
# TODO: Improve this warning with e.g. `model.config.attn_implementation = "manual"` once this is implemented.
129+
"""
130+
Copied from MllamaVisionSdpaAttention::forward:https://github.com/huggingface/transformers/blob/v4.45.2/src/transformers/models/mllama/modeling_mllama.py#L283
131+
The only differences are:
132+
- add use_flash_attention
133+
"""
134+
if output_attentions:
135+
logger.warning_once(
136+
"MllamaModel is using MllamaVisionSdpaAttention, but `torch.nn.functional.scaled_dot_product_attention` does not support `output_attentions=True`. Falling back to the manual attention implementation, "
137+
'but specifying the manual implementation will be required from Transformers version v5.0.0 onwards. This warning can be removed using the argument `attn_implementation="eager"` when loading the model.'
138+
)
139+
return super().forward(
140+
hidden_state=hidden_state,
141+
attention_mask=attention_mask,
142+
output_attentions=output_attentions,
143+
)
144+
145+
query = self.q_proj(hidden_state)
146+
key = self.k_proj(hidden_state)
147+
value = self.v_proj(hidden_state)
148+
149+
batch_size, q_seq_len, _ = query.shape
150+
_, kv_seq_len, _ = key.shape
151+
152+
query = query.view(batch_size, q_seq_len, self.num_heads, self.head_dim)
153+
key = key.view(batch_size, kv_seq_len, self.num_heads, self.head_dim)
154+
value = value.view(batch_size, kv_seq_len, self.num_heads, self.head_dim)
155+
156+
query = query.transpose(1, 2)
157+
key = key.transpose(1, 2)
158+
value = value.transpose(1, 2)
159+
if use_flash_attention and FusedSDPA:
160+
attn_output = self.fused_scaled_dot_product_attention(query, key, value, attention_mask, 0.0, False, None)
161+
else:
162+
attn_output = F.scaled_dot_product_attention(query, key, value, attn_mask=attention_mask)
163+
164+
attn_output = attn_output.transpose(1, 2).contiguous()
165+
attn_output = attn_output.reshape(batch_size, q_seq_len, -1)
166+
167+
output = self.o_proj(attn_output)
168+
169+
return output, None
170+
171+
172+
class GaudiMllamaVisionEncoderLayer(MllamaVisionEncoderLayer):
173+
def __init__(self, config: MllamaVisionConfig, is_gated: bool = False):
174+
super(GaudiMllamaVisionEncoderLayer, self).__init__(config=config, is_gated=is_gated)
175+
self.self_attn = GaudiMllamaVisionSdpaAttention(config)
176+
177+
def forward(
178+
self,
179+
hidden_state: torch.Tensor,
180+
attention_mask: Optional[torch.Tensor] = None,
181+
output_attentions: bool = None,
182+
use_flash_attention: Optional[bool] = False,
183+
):
184+
"""
185+
Copied from MllamaVisionEncoderLayer::forward:https://github.com/huggingface/transformers/blob/v4.45.2/src/transformers/models/mllama/modeling_mllama.py#L348
186+
The only differences are:
187+
- add use_flash_attention
188+
"""
189+
# Self Attention
190+
residual = hidden_state
191+
hidden_state = self.input_layernorm(hidden_state)
192+
hidden_state, attn_weights = self.self_attn(
193+
hidden_state, attention_mask=attention_mask, use_flash_attention=use_flash_attention
194+
)
195+
if self.is_gated:
196+
hidden_state = self.gate_attn.tanh() * hidden_state
197+
hidden_state = residual + hidden_state
198+
199+
# Feed forward
200+
residual = hidden_state
201+
hidden_state = self.post_attention_layernorm(hidden_state)
202+
hidden_state = self.mlp(hidden_state)
203+
if self.is_gated:
204+
hidden_state = self.gate_ffn.tanh() * hidden_state
205+
hidden_state = residual + hidden_state
206+
207+
outputs = (hidden_state,)
208+
209+
if output_attentions:
210+
outputs += (attn_weights,)
211+
212+
return outputs
213+
214+
215+
class GaudiMllamaVisionEncoder(MllamaVisionEncoder):
216+
def forward(
217+
self,
218+
hidden_states: torch.Tensor,
219+
attention_mask: Optional[torch.Tensor] = None,
220+
output_attentions: Optional[bool] = None,
221+
output_hidden_states: Optional[bool] = None,
222+
return_dict: Optional[bool] = None,
223+
use_flash_attention: Optional[bool] = False,
224+
) -> Union[Tuple, BaseModelOutput]:
225+
"""
226+
Copied from MllamaVisionEncoder::forward:https://github.com/huggingface/transformers/blob/v4.45.2/src/transformers/models/mllama/modeling_mllama.py#L394
227+
The only differences are:
228+
- add use_flash_attention
229+
"""
230+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
231+
output_hidden_states = (
232+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
233+
)
234+
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
235+
236+
encoder_states = () if output_hidden_states else None
237+
all_attentions = () if output_attentions else None
238+
239+
for encoder_layer in self.layers:
240+
if output_hidden_states:
241+
encoder_states = encoder_states + (hidden_states,)
242+
if self.gradient_checkpointing and self.training:
243+
layer_outputs = self._gradient_checkpointing_func(
244+
encoder_layer.__call__,
245+
hidden_states,
246+
attention_mask,
247+
output_attentions,
248+
)
249+
else:
250+
layer_outputs = encoder_layer(
251+
hidden_state=hidden_states,
252+
attention_mask=attention_mask,
253+
output_attentions=output_attentions,
254+
use_flash_attention=use_flash_attention,
255+
)
256+
257+
if output_attentions:
258+
all_attentions = all_attentions + (layer_outputs[1],)
259+
htcore.mark_step()
260+
hidden_states = layer_outputs[0]
261+
262+
if output_hidden_states:
263+
encoder_states = encoder_states + (hidden_states,)
264+
265+
if not return_dict:
266+
return tuple(v for v in [hidden_states, encoder_states, all_attentions] if v is not None)
267+
return BaseModelOutput(
268+
last_hidden_state=hidden_states, hidden_states=encoder_states, attentions=all_attentions
269+
)
270+
271+
110272
class GaudiMllamaTextCrossAttention(MllamaTextCrossAttention):
111273
def __init__(self, config: Optional[MllamaTextConfig] = None, layer_idx: Optional[int] = None):
112274
super().__init__(config, layer_idx)
@@ -842,6 +1004,7 @@ def forward(
8421004
output_hidden_states=output_hidden_states,
8431005
output_attentions=output_attentions,
8441006
return_dict=return_dict,
1007+
use_flash_attention=use_flash_attention,
8451008
)
8461009
cross_attention_states = vision_outputs[0]
8471010
cross_attention_states = self.multi_modal_projector(cross_attention_states).reshape(
@@ -1020,6 +1183,7 @@ def forward(
10201183
output_attentions: Optional[bool] = None,
10211184
output_hidden_states: Optional[bool] = None,
10221185
return_dict: Optional[bool] = None,
1186+
use_flash_attention: Optional[bool] = False,
10231187
) -> Union[BaseModelOutput, Tuple[torch.Tensor, ...]]:
10241188
"""
10251189
Copied from MllamaVisionModel::forward: https://github.com/huggingface/transformers/blob/v4.45.2/src/transformers/models/mllama/modeling_mllama.py#L1425
@@ -1081,6 +1245,7 @@ def forward(
10811245
attention_mask=attention_mask,
10821246
output_hidden_states=True,
10831247
output_attentions=output_attentions,
1248+
use_flash_attention=use_flash_attention,
10841249
)
10851250
hidden_state = output[0]
10861251

@@ -1099,6 +1264,7 @@ def forward(
10991264
attention_mask=attention_mask,
11001265
output_hidden_states=output_hidden_states,
11011266
output_attentions=output_attentions,
1267+
use_flash_attention=use_flash_attention,
11021268
)
11031269
hidden_state = global_output[0]
11041270

0 commit comments

Comments
 (0)