whisper : mask padded K/V in flash-attention encoder and cross-attention#3941
Open
gooofy wants to merge 1 commit into
Open
whisper : mask padded K/V in flash-attention encoder and cross-attention#3941gooofy wants to merge 1 commit into
gooofy wants to merge 1 commit into
Conversation
With flash attention enabled, the encoder self-attention and the decoder cross-attention view their K/V buffers padded to GGML_PAD(n_ctx, 256) but only write n_ctx rows, and call ggml_flash_attn_ext with a null mask. The unwritten pad rows are attended at full weight; their content is whatever the buffer holds - zeros on a fresh state, or leftovers of previous whisper_full calls with a different audio_ctx (layer strides il*n_ctx_pad shift between window sizes, so runs overwrite each other's pad regions). On a long-running server this makes transcriptions depend on request history: e.g. large-v3-turbo with audio_ctx=250 on a 3 s clip produced 5x sentence duplication on a fresh state, 2x after one audio_ctx=500 request, and clean output after full-window requests. The default full window is affected too (36 unmasked rows out of 1536), just diluted enough to go unnoticed. Fix: give both call sites a proper mask input (mirroring the decoder self-attention KQ_mask) with -INFINITY over [n_ctx, n_ctx_pad), filled in whisper_encode_internal / whisper_decode_internal. Outputs at reduced audio_ctx are now deterministic regardless of prior requests; timing is unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
With flash attention enabled, the encoder self-attention and the decoder cross-attention view their K/V buffers padded to GGML_PAD(n_ctx, 256) but only write n_ctx rows, and call ggml_flash_attn_ext with a null mask. The unwritten pad rows are attended at full weight; their content is whatever the buffer holds - zeros on a fresh state, or leftovers of previous whisper_full calls with a different audio_ctx (layer strides il*n_ctx_pad shift between window sizes, so runs overwrite each other's pad regions).
On a long-running server this makes transcriptions depend on request history: e.g. large-v3-turbo with audio_ctx=250 on a 3 s clip produced 5x sentence duplication on a fresh state, 2x after one audio_ctx=500 request, and clean output after full-window requests. The default full window is affected too (36 unmasked rows out of 1536), just diluted enough to go unnoticed.
Fix: give both call sites a proper mask input (mirroring the decoder self-attention KQ_mask) with -INFINITY over [n_ctx, n_ctx_pad), filled in whisper_encode_internal / whisper_decode_internal. Outputs at reduced audio_ctx are now deterministic regardless of prior requests; timing is unchanged.