Part of Language AI Handbook
Explains why self-attention has O(n²) complexity, how memory and compute scale quadratically with sequence length.
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Quadratic Attention Bottleneck
Transformers have revolutionized natural language processing, powering everything from chatbots to code assistants to scientific discovery tools. At the heart of their success lies self-attention: a mechanism that allows every token to directly interact with every other token in the same sequence. This all-pairs computation is both the transformer's greatest strength and its Achilles' heel. As sequence length grows, the computational and memory demands explode quadratically, creating a fundamental barrier to processing long documents, extended conversations, and book-length texts.
Think of self-attention as a room full of people where everyone must personally introduce themselves to everyone else. In a room of 10 people, that's 100 handshakes. Double the room size to 20 people and you don't get 200 handshakes. You get 400. Double it again to 40 people and you're at 1,600 handshakes. The count follows the square of the room size, and it grows far faster than intuition suggests. Self-attention has this exact property: the number of token interactions is not (linear) or even , but .
This quadratic relationship was an acceptable trade-off during the early transformer era. Most NLP tasks operated on short texts: single sentences, short paragraphs, or brief documents. BERT processed sequences of at most 512 tokens, and GPT-2 handled 1,024. At those lengths, the quadratic cost was manageable. The trouble began when practitioners wanted more: longer prompts, full-document summarization, cross-reference reasoning over entire codebases, or conversational history spanning dozens of turns. Suddenly, the quadratic bottleneck was no longer a theoretical concern but a hard engineering wall.
The key insight is that the problem extends beyond raw computational speed. Even if you had an infinitely fast processor, the quadratic memory requirement would stop you first. Attention matrices must be stored in GPU memory, and GPU memory is finite and expensive. A sequence of 32,768 tokens at standard model sizes requires more memory for attention alone than exists in any single GPU on the market. You cannot simply wait longer for the computation to finish when the data does not fit in memory.
In this chapter, we analyze why this quadratic bottleneck exists, quantify its impact on real systems, and visualize how quickly resources become exhausted. We trace the cost through every stage of the attention computation: from the initial score matrix construction through softmax normalization to the final weighted aggregation. We compare memory and compute requirements across different model configurations and sequence lengths, and we ground the abstract scaling laws in concrete GPU memory limits. Understanding this limitation sets the stage for the efficient attention variants covered in subsequent chapters, where we will see how researchers have found clever ways to break, approximate, or work around the barrier.
When the original Transformer paper (Vaswani et al., 2017) introduced self-attention, most sequence-to-sequence tasks involved sentence-length inputs. Machine translation, question answering, and text classification all operated comfortably at 128 to 512 tokens. The cost was so small at those lengths that it barely registered. It was only as the field pushed toward document-level understanding, long-form generation, and large-scale pretraining that the quadratic wall became the central challenge of transformer engineering. Today, enabling long-context models is one of the most active research areas in deep learning.
The All-Pairs Problem
Self-attention computes relationships between every pair of tokens in a sequence. For a sequence of tokens, this means pairwise interactions. This is the defining structural feature of attention, and it is the root cause of every scaling challenge discussed in this chapter.
To understand why all pairs are necessary, consider what attention is trying to accomplish. When reading the sentence "The trophy didn't fit in the suitcase because it was too big," a model needs to determine that "it" refers to "the trophy," not "the suitcase." To resolve this correctly, the word "it" must simultaneously consider "trophy," "suitcase," and "big" and compare their relevance. Attention provides exactly this capability: every token can look at every other token and decide how much weight to give each one. Restricting this to a subset of tokens would risk missing the very long-range dependencies that make attention powerful.
The complete attention formula captures this all-pairs comparison in matrix form. To compute attention for a sequence of tokens with representations of dimension , we first project each token into QKV vectors, then compute:
where:
- : the query matrix, with one row per token representing "what this token is looking for"
- : the key matrix, with one row per token representing "what this token contains"
- : the value matrix, with one row per token representing the information to aggregate
- : the dimension of queries and keys, used as a scaling factor
- : the sequence length (number of tokens)
The critical operation is , which produces an attention score matrix. Every element in this matrix represents how much token should attend to token . Computing all entries is what gives attention its power: any token can directly influence any other, regardless of distance. But this same property creates the quadratic scaling problem.
Consider the contrast with sequential processing. In a recurrent neural network, information from token 1 must propagate through tokens 2, 3, 4, and so on to reach token 100. In attention, token 1 directly connects to token 100 in a single step. This short path length is why transformers excel at capturing long-range dependencies. The price is computing all pairwise interactions up front, and that price grows quadratically.
Notice that there is no mathematical shortcut here. The score matrix entry at position requires knowledge of both token 's query and token 's key. Until you compute all scores, you cannot determine which tokens attend to which. Later in this part of the book, we will explore approximations that avoid computing the full matrix, but they do so at the cost of either accuracy or certain types of dependencies.
def count_attention_pairs(n):
"""Count the number of pairwise interactions in attention."""
return n * n
# Demonstrate quadratic growth
sequence_lengths = [128, 256, 512, 1024, 2048, 4096]
pairs = [(n, count_attention_pairs(n)) for n in sequence_lengths]Pairwise Interactions in Self-Attention:
Sequence Length Pairs Growth Factor
--------------------------------------------------
128 16,384 -
256 65,536 4.0x
512 262,144 4.0x
1,024 1,048,576 4.0x
2,048 4,194,304 4.0x
4,096 16,777,216 4.0xThe "Growth Factor" column reveals the quadratic pattern with stark clarity: doubling the sequence length quadruples the number of interactions. At 128 tokens, we compute roughly 16,000 pairs. At 4,096 tokens, this explodes to over 16 million pairs. The 4x growth for each 2x increase in sequence length is the signature of complexity, and it compounds relentlessly as sequence lengths scale toward the tens or hundreds of thousands of tokens that modern applications demand.
In practice, this means that a model processing a 32,768-token document performs roughly 65,000 times more attention interactions than the same model processing a 512-token paragraph. No other component of the transformer scales this aggressively with input length, which is why attention dominates the resource budget at long sequences.


The first panel shows the raw explosion in pair count, rising from near zero at short sequences to over 16 million at 4,096 tokens. The second panel, using logarithmic scales on both axes, reveals the underlying structure: a straight line with slope 2, confirming the relationship. Each doubling of sequence length produces exactly a 4x increase in pairs, marked along the curve.
The log-log view is particularly instructive because it turns the quadratic relationship into something visually linear, making the constant growth factor visible at every step. Any time you see a log-log plot produce a straight line with slope 2, you are looking at quadratic scaling.
Memory Analysis: The Attention Matrix
Memory is often the first constraint that prevents you from extending sequence lengths, and the source of that constraint is the attention score matrix. To understand why, consider what must be stored during a single forward pass of a transformer with self-attention.
For every attention head, the model must compute and store an matrix of attention scores before applying softmax. This matrix is not just used once: it drives the final weighted aggregation of value vectors, and during training it must be retained for the backward pass so that gradients can flow back through the softmax operation. The result is that the attention matrix lives in GPU memory for the entire duration of the forward and backward pass, consuming resources proportional to the square of the sequence length.
Think of the attention matrix as a large lookup table. For a sequence of 1,024 tokens, the table has 1,024 rows and 1,024 columns, totaling roughly one million entries. For 8,192 tokens, the table grows to 67 million entries. For 32,768 tokens, it reaches one billion entries. At two bytes per entry (fp16), that single table consumes roughly 2 gigabytes for the 32K case, and that's just one head of one layer.
The total memory required to store attention matrices across all heads and all layers in a transformer can be expressed concisely. For a model with attention heads and layers, with each layer computing an attention matrix per head at precision bytes per element:
where:
- : total memory in bytes for all attention matrices
- : number of attention heads (each head computes an independent attention pattern)
- : sequence length (number of tokens)
- : the number of entries in each attention matrix, one score per query-key pair
- : bytes per element (4 for fp32, 2 for fp16/bf16, often 2 in modern practice)
- : number of transformer layers (each layer adds another full set of attention matrices)
Notice that this formula has as its only non-linear term. Every other factor (, , ) is a constant that scales linearly with model size. The sequence length is unique in appearing squared, which is why attention memory grows so much faster than model size as context lengths increase.
Worked Example: A Concrete Memory Calculation
Let's make this concrete with a real calculation. Consider a LLaMA 7B-style model with 32 attention heads, 32 layers, and fp16 precision ( bytes). At a sequence length of 8,192 tokens:
Working through the calculation step by step:
This is before counting model weights, activations, gradients, or optimizer states. A LLaMA 7B model at 8,192 tokens already needs 128 GB for attention matrices alone, far exceeding the 80 GB capacity of an H100 GPU. This is the memory wall in concrete form.
def attention_matrix_memory_gb(n, n_heads, n_layers=1, dtype_bytes=2):
"""
Calculate memory for attention matrices.
Args:
n: Sequence length
n_heads: Number of attention heads
n_layers: Number of transformer layers
dtype_bytes: Bytes per element (2 for fp16, 4 for fp32)
Returns:
Memory in gigabytes
"""
# Each layer stores n_heads attention matrices of size n x n
bytes_per_layer = n_heads * n * n * dtype_bytes
total_bytes = bytes_per_layer * n_layers
return total_bytes / (1024**3)
# Model configurations
configs = [
{"name": "GPT-2 Small", "heads": 12, "layers": 12},
{"name": "GPT-2 Medium", "heads": 16, "layers": 24},
{"name": "LLaMA 7B", "heads": 32, "layers": 32},
]
sequence_lengths = [512, 2048, 8192, 32768]Attention Matrix Memory (fp16): GPT-2 Small (12 heads, 12 layers): n= 512: 0.07 GB n= 2,048: 1.12 GB n= 8,192: 18.00 GB n=32,768: 288.00 GB GPT-2 Medium (16 heads, 24 layers): n= 512: 0.19 GB n= 2,048: 3.00 GB n= 8,192: 48.00 GB n=32,768: 768.00 GB LLaMA 7B (32 heads, 32 layers): n= 512: 0.50 GB n= 2,048: 8.00 GB n= 8,192: 128.00 GB n=32,768: 2048.00 GB
The memory requirements reveal why long-context models are challenging. A GPT-2 Small model at 512 tokens uses only about 0.07 GB for attention matrices, which is negligible at that length. At 8,192 tokens, this grows to nearly 18 GB. At 32K tokens, a modest 12-layer model requires over 280 GB just for attention, exceeding the memory of any single GPU. Larger models with more heads and layers face even steeper memory walls at shorter sequence lengths.
The progression across model sizes is particularly telling. GPT-2 Small (a relatively tiny model by today's standards) exhausts a 24 GB GPU around 16K tokens. LLaMA 7B hits the same limit much earlier. This is why production long-context models universally rely on memory-efficient attention implementations like FlashAttention: standard attention is simply not practical for the sequence lengths that modern applications require.

The plot shows that even the smallest model configuration exceeds a 24 GB GPU around 16K tokens, and an 80 GB GPU around 32K tokens. Larger models hit these limits much sooner. This memory wall is often the first constraint encountered when extending context length, and it explains why the earliest long-context research focused on memory reduction rather than computational speedup. Saving memory, as FlashAttention famously demonstrated, can be a more impactful contribution than saving compute.
Compute Analysis: The Operations
We have seen that attention requires storing an matrix of weights. But how much computation does it take to produce those weights and use them? Understanding the computational cost helps us predict training times, estimate inference latency, and appreciate why efficient attention variants are so valuable.
The answer turns out to be floating-point operations per attention layer, where is the model dimension. To see where this comes from, let's trace through exactly what happens when attention runs, quantifying each operation precisely.
Building Intuition: What Must Be Computed?
Before diving into the math, consider what attention needs to accomplish for each token in the sequence:
- Compare this token to every other token to determine relevance scores
- Normalize those scores into a probability distribution
- Blend information from all tokens according to those probabilities
For a sequence of tokens, step 1 alone requires comparisons per token, and we have tokens, giving us comparisons. This is the fundamental source of quadratic scaling: the all-pairs comparison cannot be avoided in standard attention. Steps 2 and 3 must process the results of step 1, so they also touch entries.
Now let's quantify each step precisely and see how the costs add up.
Stage 1: Computing Attention Scores
The first operation computes how strongly each query should attend to each key. Mathematically, this is the matrix multiplication , where contains all query vectors (one per token) and contains all key vectors.
When we multiply a matrix of shape by a transposed matrix of shape , we get an output. Each entry in this output matrix is a dot product between one query and one key, requiring multiplications and additions. With such entries, the total operation count for this stage is:
where:
- : the number of query-key pairs (one score per pair)
- : the dimension of each query and key vector (typically for heads)
- : accounts for both multiplications and additions in each dot product (counted as a single fused multiply-add operation on modern hardware)
The appears because every token must be compared against every other token. There is no shortcut here: we do not know which pairs will have high attention until we compute all the scores. This is the irreducible cost of the all-pairs comparison.
Stage 2: Softmax Normalization
Raw dot products can be any real number, positive or negative, and their magnitudes depend on the model's learned parameters. To use them as weights in a weighted average, we need to convert each row of scores into a probability distribution that sums to 1. The softmax function accomplishes this, converting each row of scores into non-negative weights that sum to exactly 1.
For a row of attention scores , softmax computes:
where:
- : the raw dot product score for the -th position in the row
- : the exponential of the scaled score. This keeps all weights are positive
- : the normalizing constant, summing over all positions in the row
- : the scaling factor that prevents dot products from growing too large in magnitude, which would push softmax into regions of near-zero gradient
The scaling is a detail from the original Transformer paper, motivated by the observation that without it, dot products grow in magnitude with , pushing gradients to near zero during training. Scaling by keeps the scores in a range where softmax gradients remain healthy.
For each of the rows in the attention matrix, softmax requires exponentiating scores, summing those exponentials, and dividing each of the exponentials by the sum. This contributes roughly operations per row. With rows:
While still quadratic in , the softmax cost lacks the factor, making it smaller than score computation when is large. For typical transformers where to , softmax contributes less than 10% of the total attention FLOPs. It is not negligible, but it is not the dominant term.
Stage 3: Computing the Output
The final step uses the normalized attention weights to compute a weighted combination of value vectors. Each token's output is a blend of all tokens' values, weighted by attention. In matrix form, this is:
where the left factor is the attention weight matrix and the right factor is the value matrix.
This is another matrix multiplication: the attention weights multiplied by the value matrix produces an output. Each of the output elements requires summing across weighted values:
where:
- : the number of weight-value multiplications (every output position must aggregate from all positions)
- : the dimension of each value vector (typically equal to in standard transformers)
- : multiply-add pairs as before
This matches the cost of score computation exactly when . We have encountered two expensive operations, and they dominate the total cost of attention.

The visualization confirms our analysis: score computation and output computation each consume roughly half the total FLOPs (about 49.8% each), while softmax contributes less than 0.4%. The two matrix multiplications involving the attention matrix dominate entirely. Any optimization that targets the softmax step alone will have negligible impact on the overall compute budget.
The Complete Complexity Formula
Combining all three stages, the total computational cost of self-attention for a single head is:
where:
- : sequence length (number of tokens)
- : dimension of query and key vectors (typically , where is the number of heads)
- : dimension of value vectors (typically equal to )
- : model dimension (the full embedding size before splitting into heads)
- : number of attention heads
The simplification to holds because and are both proportional to . In standard transformers, each head operates on dimensions, and since we sum across all heads, the total work scales with the full model dimension .
Why the Quadratic Term Dominates
The formula reveals an important asymmetry in how the two factors affect complexity:
- Doubling quadruples the computation because appears squared
- Doubling only doubles the computation because appears linearly
This asymmetry determines which factor becomes the bottleneck. For a model with processing tokens, the factor dwarfs the factor by a ratio of over 20,000 to 1. The quadratic term completely dominates, which is why sequence length is the bottleneck rather than model size when processing long documents.
The practical consequence is that scaling up the model (increasing ) is far less damaging to inference speed than scaling up the context (increasing ). A model twice as wide is only twice as slow. A model with twice the context length is four times as slow. This is why researchers are far more willing to increase model dimension than context length when staying within a compute budget.
Putting Numbers to the Formula
Let's make this concrete by computing the actual FLOPs for a GPT-2 style model with across a range of sequence lengths:
def attention_flops(n, d):
"""
Calculate FLOPs for self-attention core operations.
Args:
n: Sequence length
d: Model dimension (used for Q@K^T and attn@V)
Returns:
Total FLOPs (counting multiplications and additions)
"""
# Q @ K^T: (n x d) @ (d x n) = n^2 * d multiplies + n^2 * (d-1) adds
# Simplified to 2 * n^2 * d for multiply-accumulate
score_flops = 2 * n * n * d
# Softmax: exp, sum, divide for each row = ~5 * n^2 operations
softmax_flops = 5 * n * n
# attention @ V: (n x n) @ (n x d) = n^2 * d
output_flops = 2 * n * n * d
return score_flops + softmax_flops + output_flops
d = 768
flops_by_length = [(n, attention_flops(n, d)) for n in sequence_lengths]Attention FLOPs (d=768):
Sequence Length FLOPs GFLOPs
--------------------------------------------------
512 806,617,088 0.81
2,048 12,905,873,408 12.91
8,192 206,493,974,528 206.49
32,768 3,303,903,592,448 3303.90The numbers tell the story of quadratic growth. At 512 tokens, a single attention layer performs about 1.6 billion operations, which modern GPUs handle in microseconds. At 2,048 tokens (4x longer), the count grows to roughly 26 billion operations (16x more, confirming the quadratic relationship). By 32,768 tokens, we are approaching 7 trillion operations per layer.
For a complete transformer, multiply these numbers by the layer count. A 12-layer GPT-2 at 4,096 tokens performs over 1.2 trillion attention operations. During training, backpropagation roughly triples this cost (forward pass, backward for computing gradients, backward for applying updates). The computational demands compound rapidly, and attention becomes the dominant bottleneck for long sequences.
In practice, the FLOPs budget for a long-context model is not simply "how long will this take on a single GPU." It also drives decisions about parallelism strategies, batch sizes, gradient checkpointing, and mixed-precision training. Every engineering decision that reduces the effective cost has compounding effects throughout the training pipeline.
Visualizing the Attention Matrix
The attention matrix lies at the center of the bottleneck. Visualizing its structure helps build intuition for why it is both powerful and expensive, and why efficient alternatives that avoid materializing the full matrix are so impactful.
The attention matrix is not a random array of numbers. It has structure: tokens tend to attend strongly to nearby tokens (local context), to semantically related tokens regardless of distance (content-based attention), and to certain special tokens like sentence boundaries or separator tokens (global attention). This structure is precisely what efficient attention methods exploit. If the matrix were truly dense and unstructured, there would be no way to approximate it accurately without computing all entries.



As the sequence length grows, the attention matrix balloons in size. At , the matrix is compact and easy to visualize. At , individual cells become indistinguishable. At (a common context length for modern LLMs), the matrix would contain over 67 million entries, impossible to render at a reasonable resolution.
The structured patterns visible in these matrices hint at why sparse attention methods work. Much of the attention mass concentrates on the diagonal (local context), certain global tokens, and specific positions. The full matrix contains substantial redundancy that efficient methods can exploit. A model that attends only within a local window of 256 tokens and to a small set of global tokens can capture most of the information in the full attention matrix at a fraction of the cost.
Notice also that the patterns become denser and more uniform as increases. This is not accidental: longer sequences tend to have more distributed attention patterns because there are more positions competing for weight. This observation has practical consequences for efficiency methods that rely on sparsity: they work better when attention is naturally sparse, which is more likely at short to medium sequence lengths than at very long ones.
Practical Sequence Length Limits
Given the quadratic scaling, what are the practical limits for standard attention? The answer depends on hardware constraints and whether you are training or doing inference, and the distinction between these two regimes is important.
During inference, you need to store only the current attention matrix (and possibly key-value caches for fast autoregressive generation). During training, you must also store the attention matrices for every layer simultaneously, because the backward pass needs them to compute gradients. This difference means that training is far more memory-constrained than inference, and the practical sequence length limit during training can be several times lower than during inference.
The key constraint is whether the entire computation graph fits after accounting for every memory consumer, including the attention matrices. Model weights typically occupy a fixed amount of memory regardless of sequence length. Activations from feed-forward layers and residual connections scale linearly with sequence length. Gradients and optimizer states (in training) scale with parameter count. Attention matrices then add the term on top of all this.
def estimate_max_sequence_length(
gpu_memory_gb, n_heads, n_layers, overhead_factor=0.5, dtype_bytes=2
):
"""
Estimate maximum sequence length that fits in GPU memory.
Args:
gpu_memory_gb: Available GPU memory
n_heads: Number of attention heads
n_layers: Number of layers
overhead_factor: Fraction of memory available for attention
(rest goes to weights, activations, gradients)
dtype_bytes: Bytes per element
Returns:
Maximum sequence length
"""
available_bytes = gpu_memory_gb * (1024**3) * overhead_factor
# Memory dominated by attention matrices: n_heads * n^2 * dtype_bytes * n_layers
# Solving: n^2 = available_bytes / (n_heads * dtype_bytes * n_layers)
n_squared = available_bytes / (n_heads * dtype_bytes * n_layers)
max_n = int(np.sqrt(n_squared))
return max_n
gpu_configs = [
{"name": "RTX 4090", "memory": 24},
{"name": "A100 40GB", "memory": 40},
{"name": "A100 80GB", "memory": 80},
{"name": "H100 80GB", "memory": 80},
]
model = {"heads": 12, "layers": 12} # GPT-2 Small styleEstimated Maximum Sequence Length (GPT-2 Small, batch_size=1):
GPU Memory Inference Training
----------------------------------------------------
RTX 4090 24 GB 6,688 4,230
A100 40GB 40 GB 8,635 5,461
A100 80GB 80 GB 12,211 7,723
H100 80GB 80 GB 12,211 7,723These estimates reveal a stark reality. Even on an 80 GB GPU, training a standard transformer is limited to roughly 16K-23K tokens before memory runs out. Inference allows longer sequences since gradients are not stored, but even then, sequences beyond 50K tokens become challenging. Production models that claim 100K+ context windows use specialized techniques covered in later chapters: FlashAttention for memory-efficient attention computation, grouped-query attention for reducing key-value cache size, and sliding-window attention for focusing on local context.
The overhead factor in our estimates (0.5 for inference, 0.2 for training) is a rough approximation. In practice, the exact fraction available for attention varies considerably based on model size, batch size, gradient checkpointing configuration, and optimizer choice. But the qualitative picture remains: training is always more memory-constrained than inference, and the gap grows as you add more heads and layers.

The shaded region represents sequence lengths that exceed GPU memory for training. While compute could theoretically handle longer sequences given enough time (by reducing batch size or using gradient accumulation), memory is a hard constraint that cannot be overcome without specialized techniques. This asymmetry explains why memory-efficient attention methods like FlashAttention matter in practice: they shift the memory limit rightward without changing the compute requirements, opening up sequence lengths that were previously inaccessible.
The Bottleneck Visualization
To fully appreciate the quadratic bottleneck, we can visualize how attention costs compare to other transformer components as sequence length grows. The transformer is not only attention: it also includes feed-forward networks (FFN), layer normalization, and QKV linear projections. At short sequences, these other components can dominate. At long sequences, the quadratic attention core takes over.
The key conceptual point is that every other component in a transformer scales linearly with sequence length. The feed-forward network processes each token independently, so its cost grows as . The QKV projection matrices each perform an matrix multiplication, costing . Layer normalization costs . None of these touch the term.
This means the bottleneck is not a static property of the model architecture but a dynamic one that emerges as sequences grow. For short sequences, attention is just another cheap operation. The crossover point, where attention becomes the dominant cost, depends on the ratio of to .

At short sequence lengths (128-256 tokens), the feed-forward network and projections dominate, and attention contributes less than 10% of total computation. As sequences grow, the quadratic term takes over. By 4K tokens, attention accounts for nearly half of all operations. At 16K tokens and beyond, attention consumes the vast majority of the compute budget, squeezing out everything else.
This is the attention bottleneck in visual form. Optimizing transformers for long sequences means addressing the red region in this chart. The feed-forward and projection components (orange and blue) scale linearly, which is theoretically optimal for per-token processing. It is attention's all-pairs structure that breaks linear scaling and creates the growing red region.
The crossover region around 1K-2K tokens is particularly important for practical system design. Models that process sequences mostly below this threshold can be optimized for the FFN and projection costs. Models that routinely process longer sequences must prioritize attention efficiency. This is one reason why code models and document models have driven much of the efficient attention research: they deal with long inputs by nature.
Worked Example: Tracing One Layer
To make all of these costs concrete, let's trace a single attention layer through every operation and compute the exact memory and FLOP cost at a specific sequence length. This exercise ties together everything discussed in this chapter.
Consider a single attention layer with the following configuration, representative of one layer in a GPT-2 Medium-style model:
- Sequence length: tokens
- Model dimension:
- Number of heads:
- Head dimension:
- Precision: fp16 (2 bytes per element)
# Configuration
n = 2048
d = 1024
h = 16
d_k = d // h # 64
dtype_bytes = 2 # fp16
# Step 1: Input tensor
input_tokens = n * d * dtype_bytes # shape (n, d)
# Step 2: Q, K, V projections (three separate (d x d) weight matrices)
qkv_projection_flops = 3 * 2 * n * d * d # 3 matrix mults of (n,d) x (d,d)
qkv_memory = 3 * n * d * dtype_bytes # Q, K, V each of shape (n, d)
# Step 3: QK^T for each head
score_flops = h * 2 * n * n * d_k # h heads, each (n,d_k) x (d_k,n)
score_memory = h * n * n * dtype_bytes # h attention matrices of shape (n, n)
# Step 4: Softmax (in-place, no extra memory)
softmax_flops = h * 5 * n * n
# Step 5: Attention @ V
output_flops = h * 2 * n * n * d_k # h heads, each (n,n) x (n,d_k)
output_memory = n * d * dtype_bytes # shape (n, d)
# Step 6: Output projection (d x d weight matrix)
out_proj_flops = 2 * n * d * d
out_proj_memory = n * d * dtype_bytes
# Total
total_flops = (
qkv_projection_flops
+ score_flops
+ softmax_flops
+ output_flops
+ out_proj_flops
)
total_memory_mb = (
qkv_memory + score_memory + output_memory + out_proj_memory
) / (1024**2)
attention_memory_mb = score_memory / (1024**2)Single Attention Layer Trace (n=2048, d=1024, h=16, fp16) Step FLOPs Memory ------------------------------------------------------------ QKV Projections 12,884,901,888 (weights excluded) Score Computation (QK^T) 8,589,934,592 128.0 MB Softmax Normalization 335,544,320 (in-place) Output Computation (A*V) 8,589,934,592 4.0 MB Output Projection 4,294,967,296 (weights excluded) ------------------------------------------------------------ TOTAL 34,695,282,688 148.0 MB Attention matrix memory alone: 128.0 MB Attention matrix as % of attention memory: 86.5%
The breakdown reveals that even for just 2,048 tokens, the attention score matrices already consume a significant portion of working memory. Now consider that a 24-layer model runs this computation 24 times simultaneously during training, and all attention matrices must be retained for the backward pass. This is where the per-layer cost scales to multi-gigabyte territory for longer sequences.
Notice also that the QKV projections, while not , are not trivial. At this sequence length, they consume more FLOPs than the attention core itself. This is the regime below the crossover point, where linear components still dominate. At 8,192 tokens (4x longer), the attention FLOPs would grow by 16x while the projection FLOPs grow by only 4x, pushing attention into dominance.
Motivation for Efficient Attention
The quadratic bottleneck motivates several lines of research, each tackling the problem from a different angle. The diversity of approaches reflects the fact that there is no single solution: each method makes different trade-offs between accuracy and memory, alongside compute and implementation complexity.
Understanding these trade-offs at a high level before diving into the technical details (which the subsequent chapters cover) helps you appreciate why the field has converged on multiple solutions rather than one universal approach. The right choice depends on the application: a model summarizing academic papers has different requirements than one generating code or answering questions over a long conversational history.
Instead of computing all attention scores, sparse attention methods compute only a subset. Local windows, strided patterns, and learned sparsity can reduce complexity to , where is the sequence length and is the number of positions each token attends to. For example, with a local window of 256 tokens, regardless of how long the sequence is, making the total cost linear in . The assumption underlying sparse attention is that most long-range attention weights are small and can be set to zero without significantly affecting model quality. This holds surprisingly well for many practical tasks, where local context carries the most information.
Linear attention approximates the softmax attention mechanism with kernel functions that allow associativity. The key insight is changing the order of matrix operations: instead of computing , which requires the intermediate matrix, linear attention computes . Since has shape rather than , the term disappears, achieving complexity where is the model dimension. The trade-off is that the kernel approximation may not perfectly replicate the expressiveness of softmax attention, particularly for tasks that require sharp, content-dependent attention patterns.
FlashAttention and similar methods do not reduce asymptotic complexity but dramatically reduce memory consumption by restructuring the computation. Rather than materializing the full attention matrix in GPU memory, they compute attention in small blocks, keeping only the current block in fast SRAM. This trades some recomputation for massive memory savings, enabling longer sequences within the same memory budget. FlashAttention is now standard in virtually every production transformer implementation because it requires no architectural changes and has near-zero accuracy cost.
Each approach involves trade-offs. Sparse attention sacrifices some global interactions that might be important for tasks requiring long-range reasoning. Linear attention may lose expressiveness on certain tasks, particularly those that benefit from the sharp selection behavior that softmax enables. Memory-efficient methods like FlashAttention require careful low-level implementation and may have higher constant factors on hardware that is not well-optimized for tiled computation. The following chapters explore each in detail, with concrete implementations that let you experiment with the trade-offs directly.

The gap between standard attention (red) and efficient variants grows dramatically at long sequences. At 64K tokens, sparse attention requires roughly 250 times fewer operations than standard attention. Linear attention, once its cost falls below the standard cost, provides even greater savings. This difference is what enables modern long-context models to process book-length documents: without efficient attention, no amount of hardware scaling would make 100K-token contexts practical.
Limitations of Standard Attention
The quadratic bottleneck is well-understood and extensively studied, but it is worth being explicit about what it means for real systems and what it does not mean.
Standard attention is not simply slow. It is correct, in the sense that it computes the exact full attention distribution over all tokens, with no approximation. Every efficient alternative introduces either an approximation (sparse and linear attention) or a restructuring that preserves exact answers but cannot be used everywhere (FlashAttention). This distinction matters because approximate methods may perform worse on tasks that require global, long-range attention. For short to medium sequences, standard attention is the right choice: it is simple, well-understood, and produces the best possible attention distribution.
The memory constraint is also more fundamental than the compute constraint for most practical systems. Modern GPUs can handle large amounts of computation in parallel, but GPU memory is small relative to the data sizes that long-context models need to process. A batch that does not fit in memory cannot be processed at all, regardless of compute speed. This is why FlashAttention's memory savings have been more practically impactful than its speed improvements, even though both are significant.
Another limitation that often goes unmentioned is the cost of the key-value cache during autoregressive inference. When a transformer generates text one token at a time, it reuses the key and value vectors from all previous tokens to avoid recomputing them. This KV cache grows linearly with sequence length in terms of the number of entries, but the memory it consumes is still per layer, which becomes substantial at long contexts. For a 32-layer model with a 128K-token context, the KV cache alone can consume dozens of gigabytes, creating a different kind of memory pressure from the training bottleneck.
The quadratic bottleneck is a property of the standard attention formulation, not of transformers as a class. Many transformer-like architectures have been proposed that avoid the scaling entirely while preserving the key benefits of attention: parallel computation, direct token-to-token interaction, and expressive capacity. State space models, linear recurrences, and hybrid architectures represent active areas of research aimed at breaking the quadratic barrier at the architectural level rather than the implementation level.
Summary
The quadratic attention bottleneck is a fundamental constraint that shapes transformer design and deployment at every scale. In this chapter, we quantified the scaling in both memory and compute, traced the cost through every stage of the attention computation, and visualized how attention costs grow to dominate transformer computation at long sequence lengths.
Key takeaways:
-
The all-pairs structure drives everything. Attention computes interactions because every token must be compared to every other token. This is both the source of attention's power and the root cause of its scaling problems.
-
Quadratic memory. Storing attention matrices requires memory, where is the number of attention heads, is bytes per element, and is the number of layers. This often becomes the first constraint hit when extending context length.
-
Quadratic compute. The attention core requires operations per layer, dominated by two matrix multiplications: score computation () and output aggregation (). Softmax contributes less than 1% of attention FLOPs for typical model dimensions.
-
The crossover point. At short sequences, attention is a minor cost. At long sequences (roughly 1K-4K tokens for typical models), attention becomes the dominant expense and eventually consumes over 80% of transformer FLOPs.
-
Memory before compute. Memory is typically the binding constraint, not compute. GPUs cannot process data that does not fit in memory, making memory-efficient attention more urgently important than compute-efficient attention.
-
Practical limits. Standard attention on current GPUs is limited to roughly 16K-32K tokens for training and 50K-100K tokens for inference, depending on model size and hardware. Beyond these limits, specialized techniques are required.
-
Motivation for efficiency. The quadratic bottleneck drives research into sparse attention, linear attention, and memory-efficient implementations, each trading different aspects to break the barrier. None of these are free lunches: each introduces approximations, implementation complexity, or hardware dependencies.
Understanding this bottleneck is essential for working with long-context models and for appreciating why the efficient attention techniques covered in the following chapters are so important. The wall is real, but it can be scaled with the right approaches, and knowing exactly where the cost comes from is the first step toward addressing it effectively.
Key Parameters
When analyzing attention complexity or estimating resource requirements, these parameters directly determine memory and compute costs:
-
n (sequence length): The number of tokens in the input. This is the most critical parameter since both memory and compute scale with . Typical values range from 512 (early BERT) to 128K+ (modern long-context models). Even modest increases in have dramatic effects on resource consumption.
-
d (model dimension): The embedding dimension of the model. Common values include 768 (GPT-2 Small), 4,096 (LLaMA 7B), and 8,192 (larger models). Complexity scales linearly with , making it far less impactful than sequence length.
-
h (number of heads): The number of parallel attention heads. Each head stores an independent attention matrix, so memory scales linearly with . Typical values range from 12 to 128.
-
L (number of layers): The depth of the transformer. Memory for attention matrices scales linearly with layer count. A 24-layer model uses twice the attention memory of a 12-layer model.
-
dtype_bytes: Precision of floating-point representation. Using fp16 (2 bytes) instead of fp32 (4 bytes) halves memory requirements and often doubles throughput on modern GPUs.
-
overhead_factor: When estimating maximum sequence length, this represents the fraction of GPU memory available for attention matrices after accounting for model weights and activations, plus gradients. Typical values are 0.5 for inference and 0.2 for training.
Quiz
Ready to test your understanding? Take this quick quiz to reinforce what you've learned about the quadratic attention bottleneck.
Quadratic Attention Bottleneck
Reference
Citation details
Cite or share this article.
Continue with the full handbook
This chapter is part of Language AI Handbook. Use the handbook page to browse the complete table of contents and continue reading in sequence.
Explore Language AI HandbookStay up to date
Get articles, book updates, and news delivered to your inbox.
No spam, unsubscribe anytime.
Join the community
Sign in to remove popups, track your reading progress, and join the discussion.

Comments
No comments yet. Be the first to share your thoughts!