Attention Mechanisms · May 2022
FlashAttention
intermediate
efficiencyhardware-aware
Compute exact attention 2–4× faster and with 5–20× less peak memory by recognizing that attention is memory-bandwidth-bound and tiling the computation to keep operations on-chip.
§ 1 · Premise
Attention is bottlenecked on HBM bandwidth, not FLOPs
A standard attention forward pass at sequence length and head dimension computes , then , then . Both and are matrices. On an A100 GPU, the two main memory tiers are HBM (40–80 GB, TB/s bandwidth) and per-SM SRAM ( KB on A100, TB/s). The standard implementation materializes and to HBM, then reads them back to compute — three round trips of floats each.
Dao et al. (2022, §1) measure the arithmetic intensity for typical 2022 transformer attention at and find it firmly in the memory-bound regime: the GPU spends 60–80% of wall-clock on HBM reads of , and only 20–40% on the actual matmul FLOPs that compute them. The PyTorch reference implementation in 2022 ran at roughly 5% of peak compute throughput on long-sequence attention.
The conventional optimization target for slow attention had been the FLOP count: the sparse-attention lineage (Sparse Transformer, Longformer, BigBird) and the linear-attention lineage (Performer, Linformer, Linear Attention) both replace the dense softmax with something cheaper. Dao et al.’s reframing: the FLOPs are fine, the bytes are the problem. Quadratic memory traffic, not quadratic compute, is the wall attention training hit in practice.
The technique below is exact — it returns bit-identical outputs to standard attention up to floating-point reduction order — and the resulting kernel underlies essentially every production transformer trainer in 2024–26. It is the rare optimization that frontier models adopt without any quality trade. The lineage from FlashAttention runs through FlashAttention-2 (Dao 2023, sequence-axis parallelism) to FlashAttention-3 (Shah, Dao et al. 2024, H100-specific async tensor-memory), each of which extracts another constant factor.
§ 2 · Derivation
Tiling + online softmax + recomputation
Setup. Let live in HBM. Choose block sizes (rows of per tile) and (columns of per tile) such that floats fit in SRAM — the per-tile Q-block, K-block, V-block, output accumulator, and score scratch must all be resident on-chip simultaneously. On A100 with , the paper picks for KB of SRAM, leaving room for register pressure and double-buffering.
The naive softmax — compute , subtract max, exponentiate, divide by sum — cannot run tile-by-tile because the row-wise softmax denominator depends on every column of . FlashAttention solves this with the online softmax of Milakov & Gimelshein (2018, arXiv 1805.02867). For a row of split into two partial blocks with maxima and denominators , the merged statistics are
Why this and not “compute the row max separately, then softmax”? Because that requires two passes over — one for the max, one for the exponentiation — doubling the HBM read traffic. The online form folds both into a single pass that updates running statistics as new tiles stream in.
Output accumulation uses a corresponding rescale. With running output accumulated under local max , the merged output after seeing block 2 is
The factor corrects the earlier output for the new global max; the re-weights it by the new denominator. The algebra reduces to a one-line update: each time a new K-tile arrives, the accumulator gets rescaled in place before the new tile’s softmax-times-V gets added.
The final per-row attention output written to HBM is the standard softmax-weighted average, read out of the running statistics after the full inner-loop pass:
which equals exactly — the online merge accumulates this sum without ever holding the full row in memory simultaneously.
Forward algorithm (Algorithm 1 of Dao et al. 2022). Loop over Q-tiles in the outer loop (parallelizable across CUDA blocks), K/V tiles in the inner loop. For each Q-tile of shape : zero an output accumulator , a max , and a denominator . For each inner K/V tile of shape , compute the local , take its row-max, update , exponentiate, update and with the merge equations above. After the inner loop, divide by once. Write to HBM. The output is bit-equivalent to the dense softmax up to floating-point summation order.
Backward algorithm (Algorithm 2 of Dao et al. 2022). Storing the matrix for the backward pass would defeat the purpose. Instead, FlashAttention stores only the softmax statistics from the forward pass and recomputes the relevant tiles of and inside SRAM during the backward — the same idea as gradient checkpointing applied at the kernel level. The extra FLOPs are recouped many times over by the avoided HBM traffic; the paper reports the backward at the forward cost, vs for the standard implementation.
Memory complexity. Peak activation memory drops from (standard, materialized ) to (FlashAttention, only stored across the iteration). The output is unchanged. This is the lever that unlocked training on a single GPU.
FLOP complexity. Unchanged at — the matmul work is the same. The savings are in the constant in front of the bytes term, not the FLOPs. Dao et al. (§3.3) prove a lower bound: any IO-aware attention algorithm requires HBM accesses where is SRAM size, and FlashAttention is within a constant of this lower bound. Standard attention has HBM accesses — the term dominates at long and is what FlashAttention removes.
§ 3 · Reference implementation
Sketch
# Forward sketch — illustrative, not a CUDA kernel.
# Q, K, V: [N, d] in HBM.
# Output: O, plus log-sum-exp statistics for the backward.
def flash_attention_forward(Q, K, V, B_r, B_c):
N, d = Q.shape
O = zeros((N, d)) # accumulator in HBM, written once.
m = full((N,), -inf) # running row max.
l = zeros((N,)) # running row denominator.
for q_start in range(0, N, B_r): # outer loop — Q tiles.
q = Q[q_start:q_start+B_r] # [B_r, d], resident in SRAM.
o_local = zeros((B_r, d)) # in SRAM.
m_local = full((B_r,), -inf)
l_local = zeros((B_r,))
for k_start in range(0, N, B_c): # inner loop — K, V tiles stream in.
k = K[k_start:k_start+B_c] # [B_c, d], resident in SRAM.
v = V[k_start:k_start+B_c]
s = q @ k.T / d**0.5 # [B_r, B_c] — never written to HBM.
m_new = maximum(m_local, s.max(axis=-1))
p = exp(s - m_new[:, None])
l_local = exp(m_local - m_new) * l_local + p.sum(axis=-1)
o_local = exp(m_local - m_new)[:, None] * o_local + p @ v
m_local = m_new
O[q_start:q_start+B_r] = o_local / l_local[:, None]
m[q_start:q_start+B_r] = m_local
l[q_start:q_start+B_r] = l_local
return O, m, l # m, l are reused on the backward via recomputation.
The load-bearing mechanical difference vs naive attention: the score matrix is never written to HBM. It lives in SRAM for the duration of each tile pass, gets consumed by the online softmax, and is discarded. HBM traffic per Q-tile is , vs the standard implementation’s for the materialized score matrix.
§ 4 · Empirical evidence
What FlashAttention buys, in numbers
Dao et al. (2022, Table 1) on GPT-2 small (124M params, ) end-to-end training: FlashAttention 3.5× faster than the PyTorch eager implementation, 1.6× faster than Megatron-LM’s fused attention. On GPT-2 medium (350M, ): 3.0× over PyTorch eager. At BERT-large (): 1.15× — the speedup is smaller at short sequences because the constant overhead of the tile loop matters more relative to the savings. The headline 2–4× number is for long-sequence training where the HBM-traffic saving compounds.
Peak memory measurements (Table 2 of Dao et al. 2022): GPT-2 medium at crashes on an A100 with standard attention ( GB peak) but trains under GB peak with FlashAttention — the – memory reduction headline. This is the result that unlocked the context training that the 2023 long-context wave (LongLLaMA, Claude 100K, GPT-4-32K) leaned on.
FlashAttention-2 (Dao 2023, arXiv 2307.08691, §3.1, Figure 5) reorganizes the inner loop and parallelizes across the sequence axis (FA-1 parallelized only over batch and head axes). On A100 at : FA-2 hits TFLOPS/s vs FA-1’s TFLOPS/s — 1.7× over v1. End-to-end GPT-3-style training at on 64 A100s: wall-clock speedup over FA-1.
FlashAttention-3 (Shah, Dao et al. 2024, arXiv 2407.08608, §4) targets H100’s asynchronous tensor-memory accelerator (TMA) and warp-specialized scheduling. On H100 at , fp16: 740 TFLOPS/s — of H100’s peak fp16 throughput, over FA-2. The same paper reports an fp8 variant at 1.2 PFLOPS/s on H100, further over fp16.
Independent reproduction in PyTorch’s torch.nn.functional.scaled_dot_product_attention
(merged via PyTorch 2.0, March 2023) wraps the FlashAttention-2 kernel as one of three
default backends; the same operator under JAX
(dot_product_attention) ships an equivalent
kernel. Triton implementations of FlashAttention-2
(OpenAI tutorial)
are within 5% of the CUDA kernel on A100 and have become the reference reimplementation for
custom backends.
The kernel is so universal that adopting it is invisible at the model-spec level — none of the 50+ models in this knowledge base list “FlashAttention” as an architectural choice, the way they list GQA or RoPE. It is in the system stack, not the model card. Llama-3 (Meta 2024, arXiv 2407.21783, §3) cites FlashAttention-2 by name as the training kernel; DeepSeek-V3 (arXiv 2412.19437, §3.5) uses a custom FlashAttention-3-style kernel; Gemma-2 (Gemma team 2024, arXiv 2408.00118) cites FA-2 directly. The pattern across all frontier-decoder tech reports is the same: cite, then move on. No public study finds a workload where vanilla attention is competitive once the sequence length crosses .
For numerical-precision sensitivity, Golden et al. (2024, “Is Flash Attention Stable?”, §4) compared FA-2 against the reference attention on the same model and observe that bf16 FlashAttention can produce training-loss differences of per step from accumulated reduction-order effects in the online-softmax merge — small enough that no production trainer has reported it as a quality issue, but non-zero and worth flagging. The fp32 variant is bit-equivalent up to reduction order.
Cite
BibTeX entry for the original paper
@article{arxiv2205_14135,
title = {FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness},
author = {Tri Dao, Daniel Y. Fu, Stefano Ermon, Atri Rudra, Christopher Ré},
year = {2022},
eprint = {2205.14135},
archivePrefix = {arXiv},
url = {https://arxiv.org/abs/2205.14135}
} Or cite the paper directly: arXiv:2205.14135.
Export
BibTeX
@article{arxiv_2205_14135,
title = {FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness},
author = {Tri Dao and Daniel Y. Fu and Stefano Ermon and Atri Rudra and Christopher Ré},
year = {2022},
eprint = {2205.14135},
archivePrefix = {arXiv},
url = {https://arxiv.org/abs/2205.14135}
} CSL JSON
{
"id": "arxiv_2205_14135",
"type": "article-journal",
"title": "FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness",
"author": [
{
"literal": "Tri Dao"
},
{
"literal": "Daniel Y. Fu"
},
{
"literal": "Stefano Ermon"
},
{
"literal": "Atri Rudra"
},
{
"literal": "Christopher Ré"
}
],
"issued": {
"date-parts": [
[
2022
]
]
},
"URL": "https://arxiv.org/abs/2205.14135",
"number": "2205.14135",
"source": "arXiv"
} RIS
TY - JOUR
TI - FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness
AU - Tri Dao
AU - Daniel Y. Fu
AU - Stefano Ermon
AU - Atri Rudra
AU - Christopher Ré
PY - 2022
JO - arXiv
AN - arXiv:2205.14135
UR - https://arxiv.org/abs/2205.14135
ER -