Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4032ccc

Browse files
authored
add the flash attention for the llama (PaddlePaddle#5653)
* add the flash attention for the llama * add the support for the autocast * update the float16 * update the code for auto_cast
1 parent fa4d961 commit 4032ccc

4 files changed

Lines changed: 101 additions & 66 deletions

File tree

โ€Žexamples/language_model/llama/finetune_generation.pyโ€Ž

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class ModelArgument:
5656
label_smoothing: float = field(default=0.1, metadata={"help": "The label smoothing parameter."})
5757
lr_decay_ratio: float = field(default=0.1, metadata={"help": "The ratio for learning rate decrease"})
5858
lora: bool = field(default=False, metadata={"help": "Whether to use LoRA technique"})
59+
use_flash_attention: bool = field(default=False, metadata={"help": "Whether to use flash attention"})
5960

6061

6162
def main():
@@ -105,7 +106,9 @@ def main():
105106
dtype=dtype, # todo enable set dtype to avoid additional mem usage
106107
tensor_parallel_degree=training_args.tensor_parallel_degree,
107108
tensor_parallel_rank=training_args.tensor_parallel_rank,
108-
use_recompute=True,
109+
fp16_opt_level=training_args.fp16_opt_level,
110+
use_flash_attention=model_args.use_flash_attention,
111+
use_recompute=training_args.recompute,
109112
)
110113
if model_args.lora:
111114
# TODO: hardcode parameters for now. Change after MergedLoRA is introduced

โ€Žpaddlenlp/transformers/configuration_utils.pyโ€Ž

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,8 @@ class PretrainedConfig:
446446
`float16` weights. Since the config object is stored in plain text, this attribute contains just the
447447
floating type string without the `paddle.` prefix. For example, for `paddle.float16` ``dtype` is the
448448
`"float16"` string.
449+
fp16_opt_level(`str`, *optional*):
450+
The `level` of the amp level.
449451
450452
This attribute is currently not being used during model loading time, but this may change in the future
451453
versions. But we can already start preparing for the future by saving the dtype with save_pretrained.
@@ -576,6 +578,7 @@ def __init__(self, **kwargs):
576578
self.eos_token_id = kwargs.pop("eos_token_id", None)
577579
self.sep_token_id = kwargs.pop("sep_token_id", None)
578580

581+
self.fp16_opt_level = kwargs.pop("fp16_opt_level", None)
579582
self.dtype = kwargs.pop("dtype", None)
580583

581584
self.decoder_start_token_id = kwargs.pop("decoder_start_token_id", None)

โ€Žpaddlenlp/transformers/llama/configuration.pyโ€Ž

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"pad_token_id": 0,
4040
"use_cache": False,
4141
"use_recompute": False,
42+
"use_flash_attention": False,
4243
},
4344
"facebook/llama-7b": {
4445
"hidden_size": 4096,
@@ -55,6 +56,7 @@
5556
"pad_token_id": 0,
5657
"use_cache": False,
5758
"use_recompute": False,
59+
"use_flash_attention": False,
5860
},
5961
"facebook/llama-13b": {
6062
"hidden_size": 5120,
@@ -71,6 +73,7 @@
7173
"pad_token_id": 0,
7274
"use_cache": False,
7375
"use_recompute": False,
76+
"use_flash_attention": False,
7477
},
7578
}
7679

@@ -149,8 +152,8 @@ def __init__(
149152
initializer_range=0.02,
150153
rms_norm_eps=1e-6,
151154
use_cache=True,
152-
use_pure_fp16=False,
153155
use_recompute=False,
156+
use_flash_attention=False,
154157
pad_token_id=0,
155158
bos_token_id=1,
156159
eos_token_id=2,
@@ -166,8 +169,8 @@ def __init__(
166169
self.initializer_range = initializer_range
167170
self.rms_norm_eps = rms_norm_eps
168171
self.use_cache = use_cache
169-
self.use_pure_fp16 = use_pure_fp16
170172
self.use_recompute = use_recompute
173+
self.use_flash_attention = use_flash_attention
171174
self.pad_token_id = pad_token_id
172175
self.bos_token_id = bos_token_id
173176
self.eos_token_id = eos_token_id

โ€Žpaddlenlp/transformers/llama/modeling.pyโ€Ž

Lines changed: 89 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@
2525
from paddle.distributed import fleet
2626
from paddle.distributed.fleet.utils import recompute
2727

28+
try:
29+
from paddle.nn.functional.flash_attention import flash_attention
30+
except:
31+
flash_attention = None
32+
2833
from paddlenlp.transformers.model_outputs import (
2934
BaseModelOutputWithPastAndCrossAttentions,
3035
CausalLMOutputWithCrossAttentions,
@@ -87,6 +92,60 @@ class BFloatFInfo:
8792
return np.finfo(np.float64)
8893

8994

95+
def scaled_dot_product_attention(
96+
query_states, config, key_states, value_states, attention_mask, output_attentions, is_causal=True
97+
):
98+
99+
bsz, q_len, num_heads, head_dim = query_states.shape
100+
_, kv_seq_len, _, _ = value_states.shape
101+
102+
if config.use_flash_attention and flash_attention:
103+
# Flash Attention now ignore attention mask
104+
# Current Flash Attention doesn't support attn maskt
105+
# Paddle Flash Attention input [ bz, seqlen, nhead, head_dim]
106+
# Torch Flash Attention input [ bz, nhead, seqlen, head_dim]
107+
attn_output, attn_weights = flash_attention(
108+
query_states,
109+
key_states,
110+
value_states,
111+
causal=is_causal and query_states.shape[1] != 1,
112+
return_softmax=output_attentions,
113+
)
114+
115+
attn_output = attn_output.reshape([bsz, q_len, head_dim * num_heads])
116+
return attn_output, attn_weights
117+
else:
118+
query_states = paddle.transpose(query_states, [0, 2, 1, 3])
119+
# merge with the next tranpose
120+
key_states = paddle.transpose(key_states, [0, 2, 1, 3])
121+
value_states = paddle.transpose(value_states, [0, 2, 1, 3])
122+
123+
attn_weights = paddle.matmul(query_states, key_states.transpose([0, 1, 3, 2])) / math.sqrt(head_dim)
124+
125+
if attn_weights.shape != [bsz, num_heads, q_len, kv_seq_len]:
126+
raise ValueError(
127+
f"Attention weights should be of shape {(bsz, num_heads, q_len, kv_seq_len)}, but is"
128+
f" {attn_weights.shape}"
129+
)
130+
attention_mask = attention_mask.reshape([bsz, 1, q_len, kv_seq_len])
131+
if attention_mask.shape != [bsz, 1, q_len, kv_seq_len]:
132+
raise ValueError(
133+
f"Attention mask should be of shape {(bsz, 1, q_len, kv_seq_len)}, but is {attention_mask.shape}"
134+
)
135+
attn_weights = attention_mask + attn_weights
136+
137+
if config.fp16_opt_level is not None:
138+
with paddle.amp.auto_cast(False):
139+
attn_weights = F.softmax(attn_weights, axis=-1, dtype="float32").astype(query_states.dtype)
140+
else:
141+
attn_weights = F.softmax(attn_weights, axis=-1, dtype="float32").astype(query_states.dtype)
142+
143+
attn_output = paddle.matmul(attn_weights, value_states)
144+
attn_output = attn_output.transpose([0, 2, 1, 3])
145+
attn_output = attn_output.reshape([bsz, q_len, head_dim * num_heads])
146+
return attn_output, attn_weights
147+
148+
90149
def masked_fill(x, mask, value):
91150
y = paddle.full(x.shape, value, x.dtype)
92151
return paddle.where(mask, y, x)
@@ -135,9 +194,15 @@ def __init__(self, config):
135194
self.config = config
136195

137196
def forward(self, hidden_states):
138-
with paddle.amp.auto_cast(False):
197+
default_type = hidden_states.dtype
198+
if self.config.fp16_opt_level is not None:
199+
with paddle.amp.auto_cast(False):
200+
variance = hidden_states.astype("float32").pow(2).mean(-1, keepdim=True)
201+
hidden_states = hidden_states * paddle.rsqrt(variance + self.variance_epsilon)
202+
else:
139203
variance = hidden_states.astype("float32").pow(2).mean(-1, keepdim=True)
140204
hidden_states = hidden_states * paddle.rsqrt(variance + self.variance_epsilon)
205+
141206
return hidden_states * self.weight
142207

143208

@@ -151,13 +216,14 @@ def __init__(self, dim, max_position_embeddings=2048, base=10000):
151216
freqs = paddle.einsum("i,j->ij", t, self.inv_freq)
152217
# Different from paper, but it uses a different permutation in order to obtain the same calculation
153218
emb = paddle.concat([freqs, freqs], axis=-1)
154-
self.cos_cached = emb.cos()[None, None, :, :]
155-
self.sin_cached = emb.sin()[None, None, :, :]
219+
# [bs, seqlen, nhead, head_dim]
220+
self.cos_cached = emb.cos()[None, :, None, :]
221+
self.sin_cached = emb.sin()[None, :, None, :]
156222

157223
def forward(self, x, seq_len=None):
158224
return (
159-
self.cos_cached[:, :, :seq_len, ...],
160-
self.sin_cached[:, :, :seq_len, ...],
225+
self.cos_cached[:, :seq_len, :, ...],
226+
self.sin_cached[:, :seq_len, :, ...],
161227
)
162228

163229

@@ -169,8 +235,8 @@ def rotate_half(x):
169235

170236

171237
def apply_rotary_pos_emb(q, k, cos, sin, offset: int = 0):
172-
cos = cos[..., offset : q.shape[-2] + offset, :]
173-
sin = sin[..., offset : q.shape[-2] + offset, :]
238+
cos = cos[:, offset : q.shape[1] + offset, :, :]
239+
sin = sin[:, offset : q.shape[1] + offset, :, :]
174240
q_embed = (q * cos) + (rotate_half(q) * sin)
175241
k_embed = (k * cos) + (rotate_half(k) * sin)
176242
return q_embed, k_embed
@@ -287,27 +353,15 @@ def forward(
287353
"""Input shape: Batch x Time x Channel"""
288354

289355
bsz, q_len, _ = hidden_states.shape
290-
query_states = (
291-
self.q_proj(hidden_states)
292-
.reshape(shape=[bsz, q_len, self.num_heads, self.head_dim])
293-
.transpose([0, 2, 1, 3])
294-
)
295-
key_states = (
296-
self.k_proj(hidden_states)
297-
.reshape(shape=[bsz, q_len, self.num_heads, self.head_dim])
298-
.transpose([0, 2, 1, 3])
299-
)
300-
value_states = (
301-
self.v_proj(hidden_states)
302-
.reshape(shape=[bsz, q_len, self.num_heads, self.head_dim])
303-
.transpose([0, 2, 1, 3])
304-
)
356+
query_states = self.q_proj(hidden_states).reshape(shape=[bsz, q_len, self.num_heads, self.head_dim])
357+
key_states = self.k_proj(hidden_states).reshape(shape=[bsz, q_len, self.num_heads, self.head_dim])
358+
value_states = self.v_proj(hidden_states).reshape(shape=[bsz, q_len, self.num_heads, self.head_dim])
305359

306-
kv_seq_len = key_states.shape[-2]
360+
kv_seq_len = key_states.shape[-3]
307361
offset = 0
308362

309363
if past_key_value is not None:
310-
offset = past_key_value[0].shape[-2]
364+
offset = past_key_value[0].shape[-3]
311365
kv_seq_len += offset
312366
cos, sin = self.rotary_emb(value_states, seq_len=kv_seq_len)
313367

@@ -316,46 +370,19 @@ def forward(
316370

317371
if past_key_value is not None:
318372
# reuse k, v, self_attention
319-
key_states = paddle.concat([past_key_value[0], key_states], axis=2)
320-
value_states = paddle.concat([past_key_value[1], value_states], axis=2)
373+
key_states = paddle.concat([past_key_value[0], key_states], axis=1)
374+
value_states = paddle.concat([past_key_value[1], value_states], axis=1)
321375

322376
past_key_value = (key_states, value_states) if use_cache else None
323377

324-
attn_weights = paddle.matmul(query_states, key_states.transpose([0, 1, 3, 2])) / math.sqrt(self.head_dim)
325-
326-
if attn_weights.shape != [bsz, self.num_heads, q_len, kv_seq_len]:
327-
raise ValueError(
328-
f"Attention weights should be of shape {(bsz, self.num_heads, q_len, kv_seq_len)}, but is"
329-
f" {attn_weights.shape}"
330-
)
331-
332-
attention_mask = attention_mask.reshape([bsz, 1, q_len, kv_seq_len]).astype(query_states.dtype)
333-
334-
if attention_mask is not None:
335-
if attention_mask.shape != [bsz, 1, q_len, kv_seq_len]:
336-
raise ValueError(
337-
f"Attention mask should be of shape {(bsz, 1, q_len, kv_seq_len)}, but is {attention_mask.shape}"
338-
)
339-
attn_weights = attention_mask + attn_weights
340-
attn_weights = paddle.maximum(
341-
attn_weights, paddle.to_tensor(float(finfo(query_states.dtype).min), dtype=query_states.dtype)
342-
)
343-
344-
# Upcast attention to fp32
345-
with paddle.amp.auto_cast(False):
346-
attn_weights = F.softmax(attn_weights, axis=-1, dtype="float32").astype(query_states.dtype)
347-
348-
attn_output = paddle.matmul(attn_weights, value_states)
349-
350-
if attn_output.shape != [bsz, self.num_heads, q_len, self.head_dim]:
351-
raise ValueError(
352-
f"`attn_output` should be of shape {(bsz, self.num_heads, q_len, self.head_dim)}, but is"
353-
f" {attn_output.shape}"
354-
)
355-
356-
attn_output = attn_output.transpose([0, 2, 1, 3])
357-
attn_output = attn_output.reshape([bsz, q_len, self.head_dim * self.num_heads])
358-
378+
attn_output, attn_weights = scaled_dot_product_attention(
379+
config=self.config,
380+
query_states=query_states,
381+
key_states=key_states,
382+
value_states=value_states,
383+
attention_mask=attention_mask,
384+
output_attentions=output_attentions,
385+
)
359386
attn_output = self.o_proj(attn_output)
360387

361388
if not output_attentions:
@@ -696,8 +723,7 @@ def __init__(self, config):
696723
self.config = config
697724

698725
def forward(self, hidden_states, parallel_output=False):
699-
with paddle.amp.auto_cast(False):
700-
logits = parallel_matmul(hidden_states, self.weight, parallel_output=parallel_output)
726+
logits = parallel_matmul(hidden_states, self.weight, parallel_output=parallel_output)
701727
return logits
702728

703729

0 commit comments

Comments
ย (0)