Make flash_attention effective for the Whisper encoder - #2083
Open
nilsreck wants to merge 1 commit into
Open
Conversation
The flash_attention model option currently has no effect for Whisper: WhisperEncoderLayer constructs its TransformerEncoderLayer without forwarding model.use_flash_attention(), so the parameter always falls back to its default (false) and the encoder never uses the flash path. Forwarding the flag exposes a second issue: FlashMultiHeadAttention constructs ops::FlashAttention without is_causal, which defaults to true. That is correct for decoder self-attention (the only current user of the flash path) but wrong for any encoder, which must attend bidirectionally. Pass is_causal=_is_decoder instead; this is behavior-neutral for decoders and makes the flash path usable for encoder self-attention. Validated with a WITH_FLASH_ATTN=ON source build on one RTX PRO 6000 (Blackwell): Whisper encoder forward pass 358 ms -> 116 ms (3.1x), cosine similarity 0.999667 against the non-flash encoder output, pairwise WER -0.026 on our internal test set.
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.
Problem
Setting
flash_attention=trueon a Whisper model has no effect today, for two independent reasons:WhisperEncoderLayerconstructs itsTransformerEncoderLayerwithout forwardingmodel.use_flash_attention(), so the parameter always falls back to its default (false) and the encoder never takes the flash path (src/layers/whisper.cc).FlashMultiHeadAttentionconstructsops::FlashAttentionwithoutis_causal, which defaults totrue(src/layers/flash_attention.cc). That is correct for decoder self-attention — currently the only in-tree user of the flash path — but wrong for any encoder, which must attend bidirectionally. This latent bug blocks enabling flash attention for every encoder, not just Whisper's.Fix
is_causal = _is_decoderwhen constructingops::FlashAttention. Behavior-neutral for decoders; makes the flash path correct for encoder self-attention.model.use_flash_attention()fromWhisperEncoderLayerto itsTransformerEncoderLayer.The scope is deliberately limited to Whisper:
TransformerEncoder(the generic one) also readsmodel.use_flash_attention()without forwarding it to its layers, but I only validated the Whisper encoder numerically, so I left the generic path unchanged. With theis_causalfix in place, wiring it up becomes a safe follow-up.This does not touch wheel packaging — it only affects source builds with
-DWITH_FLASH_ATTN=ON.Validation
Measured with a
WITH_FLASH_ATTN=ONsource build (based on a93c2bf) on one NVIDIA RTX PRO 6000 (Blackwell), Whisper large-v3-turbo,float16:Happy to share the comparison script if useful.