FlashAttention
Tile attention into SRAM-fitting blocks, recompute softmax statistics, and avoid materializing the n x n attention matrix.
Standard attention computes by materializing the full attention matrix in slow GPU memory. FlashAttention computes the exact same result with memory by tiling the computation into chunks that fit in fast on-chip memory. The speedup is 2-4x; the memory savings unlock contexts that wouldn't otherwise fit. It is now the default in every production Transformer training pipeline.
The memory hierarchy
GPU memory is layered:
- HBM (high-bandwidth memory): 40-80 GB on a modern GPU, ~3 TB/s bandwidth. Slow.
- SRAM (on-chip cache): ~50 MB per streaming multiprocessor, ~30 TB/s bandwidth. Fast but tiny.
Standard attention's bottleneck is HBM bandwidth: reading and writing attention scores at every step dominates the runtime, not the compute.
FLOP-wise, attention's matmul is fast; the data movement is the issue.
The FlashAttention algorithm
Dao et al. (2022)[1]. Two innovations:
1. Tiling: split the computation into blocks small enough to fit in SRAM. Compute each block fully before moving to the next.
2. Online softmax: compute softmax incrementally as new blocks arrive, without ever holding the full matrix.
The naive softmax needs the full row to compute the normalizing constant. But softmax has a useful property:
with . So you can stream through blocks, keep running max and running sum, and combine them correctly across blocks.
The full algorithm:
- Split , , into row blocks and column blocks , .
- For each row block :
- Load into SRAM.
- For each column block (left to right):
- Load , into SRAM.
- Compute in SRAM.
- Update running max and running sum.
- Update partial output in SRAM.
- Write final back to HBM.
The full matrix is never materialized; only a few blocks at a time exist in SRAM. HBM traffic drops from to where is block size, but more importantly memory drops from to .
Why it's faster
For typical sequence lengths and block sizes, FlashAttention does fewer HBM reads/writes than standard attention. The compute is the same (or slightly more due to recomputation in the backward pass), but compute was never the bottleneck.
Concrete: 2-4x faster than the standard implementation, with the ratio growing as sequence length grows.
Backward pass
The backward pass needs the same statistics. Either store them from the forward pass (cheap: instead of ) or recompute them. FlashAttention's backward also tiles over blocks, computing gradients block-by-block.
A small overhead: the backward pass redoes ~10% extra FLOPs compared to a naive implementation that stored everything. Saved memory is worth it.
FlashAttention-2 and -3
Refinements that further increase throughput:
- FA-2 (Dao, 2023): better parallelism across thread blocks, swap of inner and outer loops to use more SMs effectively. ~2x speedup over FA-1.
- FA-3 (Shah et al., 2024): NVIDIA Hopper-specific instructions (asynchronous TMA, FP8 support), another 1.5-2x on H100.
Each generation is a re-implementation for the dominant hardware generation, illustrating the IO-aware-kernel discipline.
Variants
- PagedAttention (vLLM): paginate the KV cache to handle variable- length sequences efficiently in serving. Different problem (inference), related discipline.
- Sparse FlashAttention: extend to sliding-window and other sparse attention patterns.
- Causal masking efficiency: cleaner handling of the lower- triangular mask in autoregressive decoding.
How to use it
Modern frameworks integrate FlashAttention transparently:
# PyTorch 2.x: scaled_dot_product_attention auto-dispatches to FlashAttention
y = torch.nn.functional.scaled_dot_product_attention(q, k, v, is_causal=True)The framework picks the right backend (FlashAttention, memory-efficient attention, naive) based on shapes, hardware, and dtype.
For custom kernels, the flash-attn Python package provides direct
access to the implementations.
Why it matters beyond speed
FlashAttention shifted attention from being memory-bound to being compute-bound in practice. This:
- Made long contexts (32K+ tokens) practical for training.
- Made larger batches feasible.
- Reduced the relative cost of attention in the Transformer block, shifting more focus to FFN optimization.
It is one of the most impactful systems contributions to modern deep learning, on par with mixed precision and FSDP for changing what is possible to train.
The bigger lesson
FlashAttention is the same algorithm, just implemented to be kind to the memory hierarchy. The general principle: memory bandwidth, not FLOPs, is often the bottleneck on modern hardware. Any algorithm that operates on large intermediate tensors should consider tiling, fusion, and recomputation to reduce data movement.
This thinking permeates modern kernel writing: KV cache management, mixture-of-experts routing, attention variants.
Exercises
Exercise 1. Standard attention materializes the score matrix in HBM. For a single head with sequence length and fp16 scores (2 bytes each), compute the memory of that matrix. Then state FlashAttention's memory order and why it does not store the matrix.
Solution
Step 1. The score matrix has entries.
Step 2. At 2 bytes each, bytes MB per head, per layer, for one sequence. Across many heads and layers this dominates memory and blocks long contexts.
Step 3. FlashAttention keeps only a few row/column blocks in SRAM at a time and an running max and running sum per query row, never materializing the full matrix. Its memory is : entries of statistics rather than of scores, so memory grows linearly in sequence length instead of quadratically.
Exercise 2. FlashAttention's correctness rests on the shift-invariance of softmax: for any scalar . Prove it, then explain how it lets two blocks with different running maxima be combined into one normalized output.
Solution
Step 1. Write the -th softmax component and subtract from every logit:
The common factor cancels, so the result is unchanged.
Step 2. When streaming blocks, each block is exponentiated against its own running max to stay numerically safe. When a later block raises the max to , the already-accumulated sum and output are rescaled by , which is exactly subtracting the new shift from the earlier terms.
Step 3. Because shift-invariance guarantees the final normalized softmax is independent of which constant was subtracted, rescaling partial results by and continuing yields the same output as computing softmax over the whole row at once. The block-by-block stream is exact, not approximate.
Exercise 3. A team weighs storing the forward softmax statistics ( per row) versus recomputing them in the backward pass. The recompute path adds about 10% FLOPs but saves the storage a naive backward would need. For , compare the storage of the two approaches (fp16, one head) and state which the lesson recommends and why.
Solution
Step 1. Naive backward that stored the full score matrix needs : bytes GB per head per layer, infeasible across a deep model.
Step 2. FlashAttention stores only the per-row statistics (max and sum): about values a few bytes tens of kilobytes, then recomputes the block scores on the fly during backward.
Step 3. The recompute path costs about 10% extra FLOPs but turns 2.1 GB of storage into kilobytes. Since attention was memory-bound, not compute-bound, the lesson recommends recomputation: the extra FLOPs are nearly free while the memory saving is what makes long-context backward feasible.
The next lesson covers the broader infrastructure that wraps all of these: training clusters and orchestration.
References
- [1]Dao, T., Fu, D. Y., Ermon, S., Rudra, A., & Ré, C. (2022). "FlashAttention: fast and memory-efficient exact attention with IO-awareness". NeurIPS. arXiv:2205.14135. The tiling plus online-softmax algorithm derived here.↩
- [2]Paszke, A., et al. (2019). "PyTorch: an imperative style, high-performance deep learning library". NeurIPS. arXiv:1912.01703. The framework whose
scaled_dot_product_attentionauto-dispatches to a FlashAttention backend.↩