Here's a fact that will bother you: the standard attention algorithm wastes 90% of its time waiting for data to move between memory chips on the GPU. Not computing. Waiting.
GPUs have two types of memory: fast (SRAM, ~20 MB) and slow (HBM, ~80 GB). The standard attention algorithm writes enormous intermediate matrices to slow memory, then reads them back. Over and over.
FlashAttention rewrites the attention algorithm to keep everything in fast memory. No intermediate matrices. No memory bottleneck. Same exact mathematical result. 2-4x faster. 5-20x less memory.
It's the single most impactful optimization in modern LLM inference, and understanding it shows you how the GPU actually works.
The Problem: GPU Memory Hierarchy
Think of GPU memory like your kitchen:
Memory Analogy Size Speed
SRAM (on-chip) Kitchen counter ~20 MB ~19 TB/s
HBM (off-chip) Refrigerator ~80 GB ~3 TB/s
Your kitchen counter is tiny but instant β you grab ingredients right there. The fridge is huge but you have to walk to it every time.
Standard attention cooks a meal by:
Getting ALL ingredients from the fridge β spreading them on the counter
Doing one step β putting everything BACK in the fridge
Getting everything OUT of the fridge again β doing the next step
Repeat
FlashAttention cooks by:
Getting a small batch from the fridge
Doing ALL steps on that batch without going back to the fridge
Getting the next small batch
Standard Attention: The Memory-Wasteful Way
Here's what standard attention does step by step:
python
Standard attention: Q, K, V are (N, d) where N = sequence length
Step 1: Compute attention scores
S = Q @ K.T # (N, N) matrix β written to HBM
At N=4096, d=128: S = 4096Γ4096 = 64 MB in FP16
Step 2: Apply softmax
P = softmax(S, dim=-1) # (N, N) matrix β read from HBM, write result to HBMAnother 64 MB round trip
Step 3: Multiply by values
O = P @ V # (N, d) β read P from HBM, write O to HBM
The S and P matrices are NΓN. For a sequence of 128K tokens:
S matrix = 128K Γ 128K Γ 2 bytes = 32 GB
P matrix = 128K Γ 128K Γ 2 bytes = 32 GB
Total intermediate storage = 64 GB β just for ONE attention layerThat's more than the GPU's total HBM. The model literally can't compute attention for long sequences. And even for shorter sequences, the constant reading/writing to HBM is the bottleneck β not the actual math.
This is called being memory-bound, not compute-bound.
π§
FlashAttention: IO-Aware Tiling
FlashAttention's key insight: you don't need to materialize the full NΓN matrix. You can compute attention in tiles that fit in SRAM.
The Tiling Strategy
Instead of computing the full attention matrix, FlashAttention processes blocks:
Standard: Compute ALL of QK^T β softmax β multiply by V
Flash: For each block of Q:
For each block of K, V:
Compute partial QK^T β partial softmax β accumulate into outputpython
FlashAttention pseudocode (simplified)
Divide Q, K, V into blocks that fit in SRAM
block_size = SRAM_SIZE // (3 * d) # How many rows fit in fast memory
O = zeros(N, d) # Output (in HBM)
L = zeros(N) # Running softmax denominatorfor i in range(0, N, block_size): # Outer loop: blocks of Q
Qi = Q[i:i+block_size] # Load block of Q from HBM β SRAM
Oi = zeros(block_size, d) # Local accumulator (in SRAM)
li = zeros(block_size) # Local softmax denominator (in SRAM)
mi = full(block_size, -inf) # Local softmax max (in SRAM)for j in range(0, N, block_size): # Inner loop: blocks of K, V
Kj = K[j:j+block_size] # Load block of K from HBM β SRAM
Vj = V[j:j+block_size] # Load block of V from HBM β SRAM# All computation happens in SRAM β no HBM round trips!
Sij = Qi @ Kj.T # Block attention scores (in SRAM)# Online softmax: update running max and denominator
mij = max(Sij, dim=-1)
mi_new = max(mi, mij)
li = li * exp(mi - mi_new) + sum(exp(Sij - mi_new), dim=-1)# Accumulate output
Oi = Oi * exp(mi - mi_new) + exp(Sij - mi_new) @ Vj
mi = mi_newO[i:i+block_size] = Oi / li # Write final output to HBMTotal HBM reads: O(NΒ²d / SRAM_SIZE) instead of O(NΒ²)
No NΓN intermediate matrix stored!
The Online Softmax Trick
The critical innovation: computing softmax incrementally. Normally, softmax needs to see all values first (to compute the denominator). FlashAttention uses the online softmax algorithm:
Process block 1: compute local max and sum of exponentials
Process block 2: update the running max, rescale previous results, add new exponentials
Repeat for all blocks
The math is exact. Not an approximation. The final result is bit-for-bit identical to standard attention.
π
The Numbers: Speed and Memory
Memory Savings
Sequence Length Standard Attention FlashAttention Savings
| 1K | 4 MB | 0 MB (no intermediate) | β |
|---|---|---|---|
| 4K | 64 MB | 0 MB | β |
| 16K | 1 GB | 0 MB | β |
| 128K | 64 GB (impossible!) | 0 MB | Enables it |
FlashAttention never materializes the NΓN matrix. The intermediate computation happens in SRAM tiles and is immediately consumed. Zero extra HBM usage.
Speed Improvements
Setup Standard FlashAttention Speedup
BERT (seq 512) 100 ms 45 ms 2.2x
GPT-2 (seq 1K) 180 ms 62 ms 2.9x
| Llama (seq 4K) | 520 ms | 140 ms | 3.7x |
|---|---|---|---|
| Long-context (16K) | 8.2 sec | 1.9 sec | 4.3x |
The longer the sequence, the bigger the speedup β because standard attention's HBM bottleneck grows quadratically.
FlashAttention-2: Even Faster
Paper: "FlashAttention-2: Faster Attention with Better Parallelism and Work Partitioning" (Tri Dao, 2023)
FlashAttention-2 improved on the original with:
- Better Parallelism Across Thread Blocks
FlashAttention-1 parallelized over batch and heads. FA-2 also parallelizes over the sequence dimension β splitting the outer loop across GPU streaming multiprocessors (SMs).
- Reduced Non-Matmul Operations
FA-1 spent ~50% of time on non-matmul operations (rescaling, max tracking). FA-2 restructured the algorithm to minimize these, keeping the GPU's tensor cores (which only do matmul) busy:
FlashAttention-1: ~50% matmul, ~50% other
FlashAttention-2: ~70% matmul, ~30% other
- Forward Pass Speedup
FA-1 FA-2 Improvement
| Speed | 2-4x vs standard | 2x faster than FA-1 | Up to ~8x vs standard |
|---|---|---|---|
| GPU utilization | ~30-50% | ~50-73% | Much closer to theoretical peak |
FlashAttention-3: Hopper Architecture
For: NVIDIA H100 GPUs (Hopper architecture)
FA-3 takes advantage of H100-specific hardware:
FP8 tensor cores: Run attention in FP8 precision, 2x the throughput of FP16
Asynchronous data movement: The H100's TMA (Tensor Memory Accelerator) can copy data while computing β overlap instead of wait
Warp specialization: Different warps (groups of 32 threads) handle different tasks simultaneously
FA-3 on H100:
- FP16: ~1.5x faster than FA-2
- FP8: ~2x faster than FA-2 (with negligible quality loss)
- Utilization: up to 75% of theoretical peak FLOPS
π¬
Integration: It's Everywhere
FlashAttention isn't something you install separately β it's built into every major framework:
python
PyTorch (built-in since 2.0)
import torch.nn.functional as F
Automatically uses FlashAttention when available
output = F.scaled_dot_product_attention(query, key, value, is_causal=True)PyTorch picks the fastest backend: FlashAttention, Memory-Efficient, or Math
Hugging Face Transformers
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3-8B",
attn_implementation="flash_attention_2" # Explicit FA-2)
vLLM (default)
FlashAttention is the default attention backend β no config needed
Framework FlashAttention Support
| PyTorch 2.0+ | Built-in (auto-selected) |
|---|---|
| Hugging Face Transformers | attn_implementation="flash_attention_2" |
| vLLM | Default backend |
| TensorRT-LLM | Built-in |
| llama.cpp | Custom implementation (Flash-style) |
| MLX (Apple Silicon) | Flash-inspired memory-efficient attention |
π‘οΈ
When FlashAttention Helps Most
FlashAttention's benefit depends on whether your workload is memory-bound:
Scenario Memory-Bound? FA Benefit
| Short prompts (< 512 tokens) | Less | Moderate (1.5-2x) |
|---|---|---|
| Long context (> 4K tokens) | Very | Major (3-4x) |
| Batch inference | Moderate | Good (2-3x) |
| Training | Very | Major (2-4x speed, 5-20x memory) |
| Prefill (processing prompt) | Very | Major |
| Decode (generating tokens) | Less (compute-bound) | Moderate |
The prefill phase (processing your entire prompt) is where FlashAttention shines brightest β it's processing many tokens at once, and the NΓN attention matrix is massive.
π¦
Try It Yourself
python
import torch
import torch.nn.functional as F
import time
Check FlashAttention availability
print(torch.backends.cuda.flash_sdp_enabled()) # True on modern GPUsBenchmark standard vs Flash attention
def benchmark_attention(seq_len, n_heads=32, head_dim=128, device="cuda"):
q = torch.randn(1, n_heads, seq_len, head_dim, device=device, dtype=torch.float16)
k = torch.randn(1, n_heads, seq_len, head_dim, device=device, dtype=torch.float16)
v = torch.randn(1, n_heads, seq_len, head_dim, device=device, dtype=torch.float16)
# Warm up
for _ in range(3):
F.scaled_dot_product_attention(q, k, v, is_causal=True)
torch.cuda.synchronize()
# Benchmark
start = time.time()
for _ in range(100):
F.scaled_dot_product_attention(q, k, v, is_causal=True)
torch.cuda.synchronize()
return (time.time() - start) / 100for seq_len in [512, 1024, 2048, 4096, 8192]:
t = benchmark_attention(seq_len)
print(f"Seq {seq_len:5d}: {t*1000:.2f} ms")π
Practical Takeaways
Standard attention wastes 90% of time on memory transfers β the math is fast, moving data is slow
FlashAttention tiles the computation to stay in SRAM β never materializes the NΓN attention matrix
The result is mathematically exact β not an approximation, bit-for-bit identical
FA-2 is the current production standard β 2x faster than FA-1, built into PyTorch 2.0+
Longer sequences benefit more β the speedup grows with context length
You're probably already using it β PyTorch, HF Transformers, and vLLM enable it by default
π
What's Next?
Episode 76: PagedAttention β FlashAttention optimizes how attention computes. PagedAttention optimizes how KV cache is stored. It treats GPU memory like a virtual memory system β with pages, page tables, and copy-on-write. It's the innovation behind vLLM, and it's why you can serve hundreds of concurrent users on a single GPU.
β Previous
Ep 74: Attention Variants
Next β
Ep 76: PagedAttention
Next: Episode 76 β PagedAttention
50 users chatting simultaneously. Pre-allocated GPU memory for max context length. 70% of that memory is wasted. PagedAttention fixes this.
This is part of a 98-episode series covering AI engineering from tokens to production deployment.