Why Vanilla Attention Breaks at Scale: The O(n²) Wall
A precise accounting of why standard attention becomes infeasible at long sequences: exact FLOP counts, memory costs, KV-cache growth, and the HBM bandwidth bottleneck that makes memory worse than compute.
The first two blogs built attention from scratch: the alignment model, the Q/K/V abstraction, scaled dot-product, multi-head. Everything fits on a whiteboard. The formula is clean.
Now double the sequence length. Double it again. Watch the cost explode.
This blog is a precise accounting of why vanilla attention fails at scale. Not vague gestures at “quadratic complexity” but exact FLOP counts, byte counts, and a measurement of which bottleneck actually kills you first.
The Running Model, Scaled Up
We’ve been working with three vectors. That was enough to derive the mechanism. It is not enough to understand the scaling problem.
Fix a concrete model: , heads, , layers, and fp16 throughout (2 bytes per element). We will vary sequence length during training and generated context length during autoregressive inference.
Two identities will be used repeatedly: and . These look innocent. They are not. Almost every scaling law in this post comes from expanding these two equalities inside the attention formulas.
1. What Actually Scales with Sequence Length?
Before counting anything, let us write the per-head attention computation once:
For one head, the tensors have shapes , , , , , and .
The source of the trouble is now visible. , , , and all scale like , but and scale like . This is the whole story in one line — the trouble starts the moment we materialize pairwise interactions between all positions. The quadratic term is not a side effect. It is built into the object we are computing.
Numerical check
At :
At :
The sequence length grew by a factor of , but the number of pairwise interactions grew by . This is the quadratic growth law: doubling sequence length multiplies pairwise interactions by 4, and multiplying length by 8 multiplies interactions by 64.
2. Bottleneck 1: Compute
Start with the arithmetic. This is the bottleneck people usually mention first, and for good reason: the FLOP count really does blow up.
2.1 FLOPs in
The score matrix before scaling is .
has shape , has shape , and their product has shape . By the definition of matrix multiplication, each entry is a dot product:
One dot product of length costs multiplications and additions. Using the standard FLOP convention that a multiply and an add each count as one floating-point operation, this is approximately FLOPs per entry. There are entries, so:
For our running model, :
2.2 FLOPs in Scaling, Softmax, and
Now add the rest of the attention computation. The dot-product score matrix is not the whole story.
Scaling. Dividing each entry of by is one elementwise operation per entry:
Softmax. For each of the rows, we need one pass to find the row maximum, one pass to exponentiate shifted scores, one pass to sum exponentials, and one pass to divide by the sum. That is approximately scalar operations per row, hence
Value mixing. The output matrix is with shape . By the same dot-product counting as above:
Since :
2.3 Total FLOPs Per Head
Summing the four terms:
Factor out by the distributive law of multiplication over addition:
Substitute :
For all heads:
To keep the scaling law readable, we approximate this as
The approximation comes from ignoring the small softmax/scaling constant and using .
2.4 Compare to the FFN
The raw number does not mean much by itself. The right comparison inside a transformer block is the feed-forward network.
The standard FFN maps . For one token, the first linear layer costs FLOPs, and the second linear layer costs the same , so the FFN cost per token is . Across tokens:
With :
2.5 The Compute Crossover
Attention is quadratic in . The FFN is linear in . So there must be a sequence length at which attention stops being the secondary cost and becomes the dominant one.
Using the clean approximation :
Cancel one factor of from both sides:
Divide both sides by :
So the approximate compute crossover is
If we keep the exact coefficient, the crossover is slightly lower:
2.6 Numerical table
| Attn FLOPs / layer | FFN FLOPs / layer | Dominant | |
|---|---|---|---|
| 128 | 0.034 B | 0.537 B | FFN |
| 512 | 0.545 B | 2.147 B | FFN |
| 1,024 | 2.190 B | 4.295 B | FFN |
| 2,048 | 8.760 B | 8.590 B | Near tie |
| 4,096 | 35.041 B | 17.180 B | Attention |
| 8,192 | 140.164 B | 34.360 B | Attention |
At short sequences, the FFN dominates compute. Around 2K tokens, attention catches up. Beyond that, attention becomes the arithmetic bottleneck. This is the first way vanilla attention breaks.
3. Bottleneck 2: Training Memory
The compute bottleneck hurts. The memory bottleneck usually hurts earlier.
3.1 What gets materialized
This is the crucial implementation detail that the compact formula hides. Standard attention does not merely imply an interaction pattern — it usually materializes two dense matrices per head. The first is the score matrix and the second is the attention weight matrix . Each has exactly elements. In fp16, each element is 2 bytes, so one matrix costs bytes and the pair costs bytes per head, per layer.
3.2 Numerical check
At :
So one fp16 matrix costs
which is
to a good binary-unit approximation.
Two matrices per head means
Multiply by heads:
Multiply by layers:
This is only for the two attention matrices — it does not include Q, K, V activations, FFN activations, residual streams, optimizer state, or gradients.
3.3 Memory table
| One matrix or | Two matrices / head | All heads / layer | All heads / 12 layers | |
|---|---|---|---|---|
| 512 | 0.5 MB | 1 MB | 8 MB | 96 MB |
| 1,024 | 2 MB | 4 MB | 32 MB | 384 MB |
| 2,048 | 8 MB | 16 MB | 128 MB | 1.5 GB |
| 4,096 | 32 MB | 64 MB | 512 MB | 6 GB |
| 8,192 | 128 MB | 256 MB | 2 GB | 24 GB |
| 16,384 | 512 MB | 1 GB | 8 GB | 96 GB |
By 8K tokens, the attention matrices alone already consume tens of gigabytes across layers. This is the second way vanilla attention breaks.
3.4 Why the matrices dominate everything else
It is worth making the comparison explicit, because otherwise “quadratic memory” can still sound abstract.
One Q, K, or V tensor has shape (or ). At and , one such tensor costs bytes, which is only MB. So all three linear activations together cost about MB per head. Compare that to the two dense matrices at MB per head — the ratio is . At 4K tokens, the attention matrices are already more than forty times larger than the combined Q, K, and V activations. This is the practical meaning of “quadratic memory dominates linear activations.” The objects are not just asymptotically larger — they are already dominating by large constants at practical sequence lengths.
4. Why Memory Gets Worse Than Compute: HBM Traffic
Compute tells us how many arithmetic operations happen. It does not tell us how fast the hardware can feed data to those operations.
That is where the real training bottleneck appears. Long-context attention is often limited less by multiplication than by movement.
4.1 SRAM vs HBM
Modern GPUs have fast on-chip SRAM and registers with very high bandwidth, and much larger off-chip HBM with much lower bandwidth. The exact numbers vary by device, but the pattern is stable: SRAM is extremely fast and extremely small, while HBM is much larger and much slower. The problem is that and stop fitting on-chip surprisingly early, and once they spill to HBM, every pass over them becomes a bandwidth problem.
4.2 Exact forward-pass traffic
Let us count the dominant tensor traffic for one head in a standard forward pass. This is the bookkeeping FlashAttention is designed around.
Step 1. Read and to compute :
elements read.
Write the score matrix :
elements written.
Step 2. Read to apply softmax:
elements read.
Write :
elements written.
Step 3. Read and to compute :
elements read.
Write :
elements written.
Add everything:
Since , this becomes
elements moved per head in the forward pass.
4.3 Numerical check
For our running model, and .
First compute the linear term:
Now the quadratic term:
Total:
elements moved.
The linear term is only about 1 million elements, while the quadratic term is over 50 million. The ratio is , so at 4K tokens, the traffic is already 48 times larger than the traffic. This is the core reason FlashAttention exists — the bottleneck is not only arithmetic, it is moving those matrices to and from HBM.
5. Bottleneck 3: KV Cache During Autoregressive Inference
The first two bottlenecks are primarily training-time problems. Inference introduces a different one, and in modern long-context generation it is often the decisive one.
5.1 Why the cache exists at all
During autoregressive generation, token attends over all previous tokens .
If we recomputed all keys and values from scratch at every generation step, total work over the full generated sequence would become quadratic again. So practical decoders cache the keys and values from previous steps. That cache is what makes autoregressive decoding feasible in the first place.
5.2 Cache bytes per token
For one token, one head, one layer, we store one key vector of length and one value vector of length , giving elements. In fp16, each element is 2 bytes, so the cost is bytes. Across heads and layers:
5.3 Numerical check
Substitute the running model:
First add the key and value widths:
Then multiply:
So the cache cost is
5.4 Growth table
| Context length | KV cache size |
|---|---|
| 1,024 | 24 MB |
| 4,096 | 96 MB |
| 16,384 | 384 MB |
| 32,768 | 768 MB |
| 65,536 | 1.5 GB |
| 128,000 | 3.0 GB |
This is for our small 12-layer model. The important point is not just the number but the scaling law: . The cache grows linearly with generated context length and never shrinks unless we explicitly evict or compress it.
5.5 A cleaner closed form
Because and , the cache formula simplifies in a surprisingly clean way. Start from . Since , we have , so . Now use :
5.6 Numerical check of the closed form
Substitute and :
bytes per token, exactly matching the earlier derivation.
This form is worth remembering because it shows that, for standard MHA, the per-token KV cost depends only on model depth and width. The head count disappears once we use the conventional relation .
5.7 Why this is different from the wall
This is the part that confuses almost everyone. The KV cache is not another version of the training-time wall. It is different in two ways. First, the stored memory grows linearly with context length, . Second, every new token must read the whole cache accumulated so far, so the per-step bandwidth cost also grows linearly with . That is why long-context inference feels slow even when we generate only one token at a time — each step drags a longer and longer KV history through memory. The next blog will derive this bandwidth bottleneck in much more detail. For now, the key fact is simple: training breaks on , while inference breaks on the KV cache.
6. Three Problems, Three Lineages of Solutions
Different attention papers look different because they are attacking different bottlenecks. Once we separate the bottlenecks, the literature becomes much easier to parse.
6.1 Compute bottleneck
The first bottleneck is that and scale quadratically in sequence length. Typical fixes include sparse attention, local-window attention, linear attention, and state-space replacements — all of which change what pairwise interactions are computed.
6.2 Memory / HBM bottleneck
The second bottleneck is that materializing and forces large tensors through HBM. The canonical fix here is FlashAttention. It does not change the attention formula — it changes the schedule, tiling the computation so the large matrices are never written to HBM in the first place.
6.3 KV-cache bottleneck
The third bottleneck is that inference stores and rereads one K and one V vector per layer, per head, per token. Typical fixes include Multi-Query Attention (MQA), Grouped-Query Attention (GQA), Multi-head Latent Attention (MLA), sliding-window caches, and KV quantization, all of which change what gets stored across decoding steps.
6.4 Why one fix does not solve the others
This is the unifying insight of the whole post. FlashAttention solves the training memory traffic problem, but it does not shrink the inference KV cache. GQA shrinks the inference KV cache, but it does not remove the quadratic training-time interaction pattern. Sparse or linear attention reduce quadratic arithmetic, but they may or may not help the KV cache, depending on whether they also change what is stored. So when two papers claim to make attention “efficient,” they may not be addressing the same bottleneck at all.
Summary
Vanilla attention breaks in three distinct ways. First, its arithmetic cost grows as because every token interacts with every other token. Second, its training-time memory and HBM traffic are dominated by the dense score and probability matrices. Third, its autoregressive inference path accumulates a KV cache whose size grows linearly with context and whose bandwidth cost grows with every generated token.
These three bottlenecks are why the literature branches: sparse and linear methods attack quadratic compute, FlashAttention attacks training-time memory traffic, and MQA/GQA/MLA attack the KV cache. The next blog zooms in on that third bottleneck and derives the KV-cache story much more deeply.
Previous: From Soft Alignment to Queries, Keys, and Values
Next: What Can We Actually Modify in Attention?
Enjoyed this post?
Subscribe to get notified when I publish new posts. No spam, unsubscribe anytime.