FlashAttention: The Algorithm That Beat the Memory Wall
How a tiled, IO-aware CUDA kernel turned exact attention into something GPUs can actually afford to run at scale.

FlashAttention is a fast, memory-efficient exact attention algorithm. It uses tiling to reduce the number of memory reads/writes between GPU High Bandwidth Memory (HBM) and GPU on-chip SRAM.
- FlashAttention wins by reducing memory traffic, not by chasing a better FLOP count.
- The kernel streams Q, K, and V through tiny on-chip tiles, then updates softmax statistics online so the full matrix never has to exist in global memory.
- The repository is valuable because it connects a friendly Python API to aggressively specialized CUDA code without giving up exact attention.
- Varlen support turns the algorithm from a benchmark trick into something that fits messy production batches.
The Real Bottleneck Was Never Compute
Standard attention looks like a math problem, but on a GPU it behaves like a traffic problem. The expensive part is not the dot products themselves. It is the constant shuttling of a massive N × N score matrix through slow global memory while the chip waits.
That is the idea FlashAttention turns inside out. Instead of materializing the whole matrix, it streams small tiles of Q, K, and V through fast on-chip memory, does the work there, and writes out only what is needed. Exact attention stays exact. The memory bill drops.
A Tile, a Register File, and a Trick Called Online Softmax
The core algorithm is deceptively simple once you see it. The kernel takes a block of queries, multiplies it against a block of keys, and uses that partial result to update two running values: the maximum score seen so far and the normalization constant for softmax. Then it folds the matching value block into the output accumulator.
That is what lets FlashAttention stay exact without ever storing the full matrix. The algebra is arranged so each tile can revise the previous state instead of forcing a complete replay. The register file and shared memory become the working set. HBM becomes a brief checkpoint, not the main workspace.
for each Q_tile:
m = running_max
l = running_lse
O = running_output
for each K_tile, V_tile:
S = Q_tile @ K_tile^T
m_new = max(m, max(S))
P = exp(S - m_new)
l_new = exp(m - m_new) * l + sum(P)
O = (exp(m - m_new) * l / l_new) * O + (P @ V_tile) / l_new
m, l = m_new, l_new
write O
How the Repo Connects Python to Bare-Metal CUDA
The repository is a stack, not a single trick. In flash_attn_interface.py, Python registers the operator and handles dispatch. In flash_api.cpp, C++ translates PyTorch tensors into a launchable parameter struct. In flash_fwd_kernel.h, the CUDA kernel executes the tiled algorithm with the right specialization for the hardware.
That bridge matters because performance code fails when the glue is sloppy. The host side has to preserve tensor strides, data types, masking mode, dropout, and sequence layout. The kernel only gets to be fast if the parameters that reach it are already precise.
The major bottleneck in Transformer training is the self-attention mechanism, which is O(T^2) in sequence length. FlashAttention is a critical optimization that makes this O(T) in memory and much faster in practice.
Why Templates Matter Here
FlashAttention is not one kernel. It is a family of compiled variants. The code specializes for head sizes, masking modes, dropout, GPU generation, and layout details. That specialization removes inner-loop branches and lets the compiler generate a kernel that matches the shape of the workload.
This is why the repo feels stricter than a normal library. It is not trying to be maximally generic. It is trying to be exact and fast for a narrow but important class of Transformer workloads.
| Dimension | Generic attention | FlashAttention |
|---|---|---|
| Matrix handling | Materializes large score matrices | Streams tiles and avoids the full matrix |
| Memory pressure | Heavy HBM reads and writes | Keeps working data in SRAM and registers |
| Kernel shape | One path with more branching | Many specialized templates |
| Exactness | Exact | Exact |
| Best use case | Convenience and baseline use | Long-context, production-grade training |
Varlen Is the Quiet Superpower
Real batches are messy. Some sequences are short, some are long, and padding them all to the same length wastes memory and compute. FlashAttention’s varlen path accepts packed sequences, so the kernel can process uneven inputs without paying for dead tokens.
That matters because production data rarely behaves like a clean benchmark. Varlen is not the headline feature, but it is the kind of feature that decides whether a fast kernel is useful outside a paper.
| Batch style | Padded attention | Varlen FlashAttention |
|---|---|---|
| Sequence shape | Uniform length after padding | Packed variable-length sequences |
| Waste | Tokens and memory spent on padding | Only real tokens are processed |
| Throughput | Drops as padding grows | Improves on messy real batches |
| Practicality | Easy but expensive | More complex, but production-friendly |
FlashAttention vs. the Old Way
The comparison that matters is not only speed. It is exactness, memory traffic, and whether long context stays viable as sequence length grows. Approximate methods like Reformer or Performer change the math to dodge the quadratic wall. FlashAttention keeps the math and fixes the memory path.
| Method | Exact? | Full matrix materialized? | HBM traffic | Long-context fit |
|---|---|---|---|---|
| Standard PyTorch attention | Yes | Yes | High | Poor once sequences get long |
| FlashAttention | Yes | No | Low | Strong |
| xFormers-style optimized attention | Usually yes | Sometimes reduced, but not the core breakthrough | Moderate | Good, depending on backend |
| Approximate methods | No | No | Varies | Often good, but with accuracy trade-offs |
What the Repo Says About the GPU Era
FlashAttention is bigger than a kernel. It is a reminder that modern performance work is about respecting the memory hierarchy. When hardware gets more capable, the winning software is often the one that moves less, not the one that computes more.
That is why this repo became infrastructure. It is a software pattern disguised as an optimization: tile the problem, keep the hot data close, and make the expensive path disappear.





