Chunk the batch to keep FlashAttention's backward in its index range - #1184
Open
priorphil wants to merge 2 commits into
Open
Chunk the batch to keep FlashAttention's backward in its index range#1184priorphil wants to merge 2 commits into
priorphil wants to merge 2 commits into
Conversation
A FlashAttention backward fails with an illegal memory access once batch * heads * round_up(seq_q, 128) * head_dim exceeds 2**31. The forward is fine at the same shapes, and the memory-efficient backend is fine at all of them. `_torch_sdpa` already chunks the batch to stay under the CUDA grid limit, so this reuses that loop with a second bound on the element count. The boundary is exact: a padded count of exactly 2**31 passes and 1.001 * 2**31 fails. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A head dim of 16 fails at half the raw element count, because the kernel counts it as 32: (800, 8, 10496, 16) is 1,074,790,400 elements, well inside 2**31, and still faults, while (400, 8, 10496, 32) at the identical count passes. Rounding the head dim up to 32 brings that case back under the same bound. The floor is 32 rather than 64: (400, 8, 10496, 16) passes, which it would not if 16 were counted as 64. Swept head dims 16, 32, 64 and 128; 20 shapes now agree with batch * heads * round_up(seq_q, 128) * max(head_dim, 32) > 2**31. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
priorphil
marked this pull request as ready for review
August 17, 2026 09:16
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.
Generated by Claude Code.
What
A FlashAttention backward fails with
CUDA error: an illegal memory access was encounteredonceThe forward is fine at the same shapes, and the memory-efficient backend is fine at all of them.
_torch_sdpaalready chunks the batch to keepbatch * headsunder the CUDA grid limit. This adds a second bound to that same loop, on the element count above.Both roundings matter, and each one on its own makes the naive reading wrong:
Reproducing
Needs a CUDA device with ~24 GiB free.
Swapping
FLASH_ATTENTIONforEFFICIENT_ATTENTIONmakes it pass.The small-head-dim case is worth reproducing too, since it is the one a check on the raw element count would miss.
(800, 8, 10496, 16)is 1,074,790,400 elements, half the bound, and fails.Where the boundary is
Measured on an RTX PRO 6000, torch 2.9.0+cu128, bfloat16. One process per shape, since a fault leaves the CUDA context unusable. "counted" is
batch * heads * round_up(seq_q, 128) * max(head_dim, 32).The
799and512rows sit either side of the boundary within 0.03%, and the400 / 16versus800 / 16pair fixes the head-dim floor at 32 rather than 64.Caveats
heads * round_up(seq_q, 128) * max(head_dim, 32) > 2**31, which no shape here reaches.Tests
tests/test_architectures/test_shared/test_scaled_dot_product_attention.py:_torch_sdpaon meta tensors and assert the chunking: over the bound it splits and every call lands inside it, the head-dim-16 case over the bound also splits (its raw count looks safe, so this is the one that catches a check which ignores the padding), inside the bound it stays a single call, and a non-FlashAttention backend is not split. These need no GPU and no memory.slowtest that runs a failing shape end to end, skipped unless a CUDA device has ~24 GiB free.pytest tests/test_architectures/test_shared tests/test_architectures/test_attention_backends.py tests/test_architectures/test_chunked_evaluate.pypasses (30 passed, 9 skipped).Verified on the GPU: the
slowtest fails unpatched and passes patched. A larger model that previously failed at these shapes now completes, both at the shape where it first failed and at one 1.34x beyond it.