Implement the scaled dot product attention with softmax. Arguments --------- softmax_scale: The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout: The
| 154 | |
| 155 | |
| 156 | class FlashSelfAttention(torch.nn.Module): |
| 157 | # Extracted from https://github.com/microsoft/Megatron-DeepSpeed/blob/main/megatron/model/transformer.py |
| 158 | """Implement the scaled dot product attention with softmax. |
| 159 | Arguments |
| 160 | --------- |
| 161 | softmax_scale: The temperature to use for the softmax attention. |
| 162 | (default: 1/sqrt(d_keys) where d_keys is computed at |
| 163 | runtime) |
| 164 | attention_dropout: The dropout rate to apply to the attention |
| 165 | (default: 0.0) |
| 166 | """ |
| 167 | |
| 168 | def __init__(self, causal=False, softmax_scale=None, attention_dropout=0.0, |
| 169 | device=None, dtype=None): |
| 170 | super().__init__() |
| 171 | assert flash_attn_unpadded_func is not None, ('Please install FlashAttention first, ' |
| 172 | 'e.g., with pip install flash-attn') |
| 173 | assert rearrange is not None, 'Please install einops first, e.g., with pip install einops' |
| 174 | self.causal = causal |
| 175 | self.softmax_scale = softmax_scale |
| 176 | self.dropout_p = attention_dropout |
| 177 | |
| 178 | def forward(self, q, k, v): |
| 179 | """Implements the multihead softmax attention. |
| 180 | Arguments |
| 181 | --------- |
| 182 | q, k, v: The tensor containing the query, key, and value. (B, S, H, D) |
| 183 | """ |
| 184 | assert all((i.dtype in [torch.float16, torch.bfloat16] for i in (q, k, v))) |
| 185 | assert all((i.is_cuda for i in (q, k, v))) |
| 186 | |
| 187 | batch_size, seqlen_q = q.shape[0], q.shape[1] |
| 188 | seqlen_k = k.shape[1] |
| 189 | |
| 190 | q, k, v = [rearrange(x, 'b s ... -> (b s) ...') for x in [q, k, v]] |
| 191 | cu_seqlens_q = torch.arange(0, (batch_size + 1) * seqlen_q, step=seqlen_q, dtype=torch.int32, |
| 192 | device=q.device) |
| 193 | if self.training: |
| 194 | # during training q,k,v always have same seqlen |
| 195 | assert seqlen_k == seqlen_q |
| 196 | |
| 197 | is_causal = self.causal |
| 198 | cu_seqlens_k = cu_seqlens_q |
| 199 | dropout_p = self.dropout_p |
| 200 | else: |
| 201 | # turn off FA causal mask after first inference autoregressive iteration |
| 202 | # only on first autoregressive step q,k,v have same seqlen |
| 203 | is_causal = seqlen_q == seqlen_k |
| 204 | cu_seqlens_k = torch.arange(0, (batch_size + 1) * seqlen_k, step=seqlen_k, dtype=torch.int32, |
| 205 | device=q.device) |
| 206 | dropout_p = 0 |
| 207 | |
| 208 | output = flash_attn_unpadded_func( |
| 209 | q, k, v, cu_seqlens_q, cu_seqlens_k, seqlen_q, seqlen_k, |
| 210 | dropout_p=dropout_p, |
| 211 | softmax_scale=self.softmax_scale, causal=is_causal |
| 212 | ) |
| 213 |