Quadratic Attention Bottleneck

Michael BrenndoerferUpdated June 21, 202548 min read

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 nn (linear) or even 2n2n, but n2n^2.

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 n2n^2 barrier.

Historical Context: Why Quadratic Was Acceptable

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 n2n^2 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 nn tokens, this means n2n^2 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 nn tokens with representations of dimension dkd_k, we first project each token into QKV vectors, then compute:

Attention(Q,K,V)=softmax(QKTdk)V\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V

where:

  • QRn×dkQ \in \mathbb{R}^{n \times d_k}: the query matrix, with one row per token representing "what this token is looking for"
  • KRn×dkK \in \mathbb{R}^{n \times d_k}: the key matrix, with one row per token representing "what this token contains"
  • VRn×dvV \in \mathbb{R}^{n \times d_v}: the value matrix, with one row per token representing the information to aggregate
  • dkd_k: the dimension of queries and keys, used as a scaling factor
  • nn: the sequence length (number of tokens)

The critical operation is QKTQK^T, which produces an n×nn \times n attention score matrix. Every element (i,j)(i, j) in this matrix represents how much token ii should attend to token jj. Computing all n2n^2 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 (i,j)(i, j) requires knowledge of both token ii's query and token jj's key. Until you compute all n2n^2 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.

In[3]:
Code
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]
Out[4]:
Console
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.0x

The "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 O(n2)O(n^2) 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.

Out[5]:
Visualization
Line plot with parabolic growth of pairwise interactions on linear scale.
Pairwise interaction count on a linear scale, showing the parabolic explosion from near zero at short sequences to over 16 million at 4096 tokens. The area under the curve grows far faster than a linear relationship would suggest.
Log-log plot showing linear relationship with slope 2 and 4x growth annotations.
The same data on a log-log scale, revealing the underlying structure as a straight line with slope 2. Each doubling of sequence length produces exactly 4x more pairs, confirming the n-squared relationship with the annotated 4x markers.

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 n2n^2 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 O(n2)O(n^2) 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 n×nn \times n 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 n×nn \times n 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 hh attention heads and LL layers, with each layer computing an n×nn \times n attention matrix per head at precision bb bytes per element:

Mattn=h×n2×b×LM_{\text{attn}} = h \times n^2 \times b \times L

where:

  • MattnM_{\text{attn}}: total memory in bytes for all attention matrices
  • hh: number of attention heads (each head computes an independent n×nn \times n attention pattern)
  • nn: sequence length (number of tokens)
  • n2n^2: the number of entries in each attention matrix, one score per query-key pair
  • bb: bytes per element (4 for fp32, 2 for fp16/bf16, often 2 in modern practice)
  • LL: number of transformer layers (each layer adds another full set of attention matrices)

Notice that this formula has n2n^2 as its only non-linear term. Every other factor (hh, bb, LL) is a constant that scales linearly with model size. The sequence length nn 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 (b=2b = 2 bytes). At a sequence length of 8,192 tokens:

Mattn=32×81922×2×32M_{\text{attn}} = 32 \times 8192^2 \times 2 \times 32

Working through the calculation step by step:

81922=67,108,864 entries per head per layer×2 bytes=134,217,728 bytes per head per layer×32 heads=4,294,967,296 bytes per layer×32 layers=137,438,953,472 bytes128 GB\begin{aligned} 8192^2 &= 67{,}108{,}864 \text{ entries per head per layer} \\ \times 2 \text{ bytes} &= 134{,}217{,}728 \text{ bytes per head per layer} \\ \times 32 \text{ heads} &= 4{,}294{,}967{,}296 \text{ bytes per layer} \\ \times 32 \text{ layers} &= 137{,}438{,}953{,}472 \text{ bytes} \approx 128 \text{ GB} \end{aligned}

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.

In[6]:
Code
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]
Out[7]:
Console
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.

Out[8]:
Visualization
Log-scale plot showing attention memory growing quadratically with sequence length for different model sizes, with GPU memory limits marked as horizontal dashed lines.
Attention matrix memory consumption as sequence length increases for three model configurations. Each curve follows the same quadratic shape but is offset vertically by model size. The horizontal dashed lines mark the memory capacity of common GPUs. Where a curve crosses a dashed line, that model can no longer fit its attention matrices in that GPU at standard precision.

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 O(n2d)O(n^2 d) Operations

We have seen that attention requires storing an n×nn \times n 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 O(n2d)O(n^2 d) floating-point operations per attention layer, where dd 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:

  1. Compare this token to every other token to determine relevance scores
  2. Normalize those scores into a probability distribution
  3. Blend information from all tokens according to those probabilities

For a sequence of nn tokens, step 1 alone requires nn comparisons per token, and we have nn tokens, giving us n×n=n2n \times n = n^2 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 n2n^2 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 QKTQK^T, where QQ contains all query vectors (one per token) and KK contains all key vectors.

When we multiply a matrix of shape (n×dk)(n \times d_k) by a transposed matrix of shape (dk×n)(d_k \times n), we get an (n×n)(n \times n) output. Each entry in this output matrix is a dot product between one query and one key, requiring dkd_k multiplications and dk1d_k - 1 additions. With n2n^2 such entries, the total operation count for this stage is:

Score FLOPs2n2dk\text{Score FLOPs} \approx 2 \cdot n^2 \cdot d_k

where:

  • n2n^2: the number of query-key pairs (one score per pair)
  • dkd_k: the dimension of each query and key vector (typically d/hd / h for hh heads)
  • 22: accounts for both multiplications and additions in each dot product (counted as a single fused multiply-add operation on modern hardware)

The n2n^2 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 nn attention scores s1,s2,,sns_1, s_2, \ldots, s_n, softmax computes:

softmax(si)=esi/dkj=1nesj/dk\text{softmax}(s_i) = \frac{e^{s_i / \sqrt{d_k}}}{\sum_{j=1}^{n} e^{s_j / \sqrt{d_k}}}

where:

  • sis_i: the raw dot product score for the ii-th position in the row
  • esi/dke^{s_i / \sqrt{d_k}}: the exponential of the scaled score. This keeps all weights are positive
  • j=1nesj/dk\sum_{j=1}^{n} e^{s_j / \sqrt{d_k}}: the normalizing constant, summing over all positions in the row
  • dk\sqrt{d_k}: the scaling factor that prevents dot products from growing too large in magnitude, which would push softmax into regions of near-zero gradient

The dk\sqrt{d_k} scaling is a detail from the original Transformer paper, motivated by the observation that without it, dot products grow in magnitude with dkd_k, pushing gradients to near zero during training. Scaling by dk\sqrt{d_k} keeps the scores in a range where softmax gradients remain healthy.

For each of the nn rows in the attention matrix, softmax requires exponentiating nn scores, summing those nn exponentials, and dividing each of the nn exponentials by the sum. This contributes roughly 5n5n operations per row. With nn rows:

Softmax FLOPs5n2\text{Softmax FLOPs} \approx 5 \cdot n^2

While still quadratic in nn, the softmax cost lacks the dkd_k factor, making it smaller than score computation when dkd_k is large. For typical transformers where dk=64d_k = 64 to 128128, 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:

Output=softmax ⁣(QKTdk)V\text{Output} = \text{softmax}\!\left(\frac{QK^T}{\sqrt{d_k}}\right) \cdot V

where the left factor is the (n×n)(n \times n) attention weight matrix and the right factor VV is the (n×dv)(n \times d_v) value matrix.

This is another matrix multiplication: the (n×n)(n \times n) attention weights multiplied by the (n×dv)(n \times d_v) value matrix produces an (n×dv)(n \times d_v) output. Each of the n×dvn \times d_v output elements requires summing across nn weighted values:

Output FLOPs2n2dv\text{Output FLOPs} \approx 2 \cdot n^2 \cdot d_v

where:

  • n2n^2: the number of weight-value multiplications (every output position must aggregate from all nn positions)
  • dvd_v: the dimension of each value vector (typically equal to dkd_k in standard transformers)
  • 22: multiply-add pairs as before

This matches the cost of score computation exactly when dv=dkd_v = d_k. We have encountered two expensive O(n2d)O(n^2 d) operations, and they dominate the total cost of attention.

Out[9]:
Visualization
Horizontal bar chart showing FLOPs breakdown: score computation and output computation are roughly equal and much larger than softmax.
Breakdown of attention FLOPs across the three computational stages for a model with d=768 at sequence length n=1024. Score computation and output computation each contribute approximately half of all attention operations. Softmax normalization is negligible at under 0.4 percent. This shows that the two matrix multiplications completely dominate the attention cost.

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 n×nn \times n 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:

FLOPs=2n2dkscores+5n2softmax+2n2dvoutput=O(n2d)\text{FLOPs} = \underbrace{2n^2 d_k}_{\text{scores}} + \underbrace{5n^2}_{\text{softmax}} + \underbrace{2n^2 d_v}_{\text{output}} = O(n^2 d)

where:

  • nn: sequence length (number of tokens)
  • dkd_k: dimension of query and key vectors (typically d/hd / h, where hh is the number of heads)
  • dvd_v: dimension of value vectors (typically equal to dkd_k)
  • dd: model dimension (the full embedding size before splitting into heads)
  • hh: number of attention heads

The simplification to O(n2d)O(n^2 d) holds because dkd_k and dvd_v are both proportional to dd. In standard transformers, each head operates on d/hd/h dimensions, and since we sum across all heads, the total work scales with the full model dimension dd.

Why the Quadratic Term Dominates

The formula O(n2d)O(n^2 d) reveals an important asymmetry in how the two factors affect complexity:

  • Doubling nn quadruples the computation because nn appears squared
  • Doubling dd only doubles the computation because dd appears linearly

This asymmetry determines which factor becomes the bottleneck. For a model with d=768d = 768 processing n=4,096n = 4,096 tokens, the n2=16,777,216n^2 = 16{,}777{,}216 factor dwarfs the d=768d = 768 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 dd) is far less damaging to inference speed than scaling up the context (increasing nn). 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 d=768d = 768 across a range of sequence lengths:

In[10]:
Code
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]
Out[11]:
Console
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.90

The 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 n2n^2 cost has compounding effects throughout the training pipeline.

Visualizing the Attention Matrix

The n×nn \times n 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 n2n^2 entries.

Out[12]:
Visualization
16x16 attention matrix heatmap showing full pairwise attention weights with darker diagonal indicating self-attention.
Attention matrix for n=16 tokens. The matrix is compact enough to see individual entries clearly. Strong diagonal weights indicate local context attention, while bright rows and columns at special positions reflect global token patterns.
64x64 attention matrix heatmap showing more complex attention patterns across a longer sequence.
Attention matrix for n=64 tokens. The matrix is 16 times larger in area than the n=16 case. Structural patterns become more apparent: a strong diagonal band for local context, bright spots at quarter-sequence positions, and distributed attention in the off-diagonal regions.
256x256 attention matrix heatmap where individual cells are barely visible. This shows scale.
Attention matrix for n=256 tokens, containing 65,536 individual entries. Individual cells are barely distinguishable, illustrating how the matrix becomes dense and computationally expensive. At n=8192, this matrix would contain over 67 million entries.

As the sequence length grows, the attention matrix balloons in size. At n=16n=16, the matrix is compact and easy to visualize. At n=256n=256, individual cells become indistinguishable. At n=8192n=8192 (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 n2n^2 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 nn 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 O(n2)O(n^2) term on top of all this.

In[13]:
Code
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 style
Out[14]:
Console
Estimated 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,723

These 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.

Out[15]:
Visualization
Log-log plot showing one normalized quadratic curve for both memory and compute, with GPU memory limits marked for training and inference scenarios.
Memory and compute requirements as sequence length increases, normalized to their values at n=512. Both scale quadratically (the single purple curve represents both), but memory hits a hard wall while compute can in principle be spread across time by processing smaller batches. The vertical dashed lines mark where an 80 GB GPU runs out of memory for attention matrices under training and inference regimes. The shaded region beyond the training limit requires either memory-efficient attention or gradient checkpointing.

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 O(nd2)O(nd^2). The QKV projection matrices each perform an (n×d)×(d×d)(n \times d) \times (d \times d) matrix multiplication, costing O(nd2)O(nd^2). Layer normalization costs O(nd)O(nd). None of these touch the n2n^2 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 nn to dd.

Out[16]:
Visualization
Stacked area chart showing feed-forward network costs staying linear while attention costs grow quadratically to dominate at long sequence lengths.
Proportion of total transformer FLOPs consumed by each component as sequence length increases, for a model with d=768. At short sequences (128-256 tokens), the feed-forward network and projection matrices dominate, and attention contributes less than 10 percent. As sequences grow past the crossover region (1K-2K tokens), the quadratic attention core takes an ever-increasing share. By 16K tokens, attention accounts for over 80 percent of all transformer operations.

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: n=2048n = 2048 tokens
  • Model dimension: d=1024d = 1024
  • Number of heads: h=16h = 16
  • Head dimension: dk=d/h=64d_k = d / h = 64
  • Precision: fp16 (2 bytes per element)
In[17]:
Code
# 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)
Out[18]:
Console
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 O(n2)O(n^2), 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.

Sparse Attention

Instead of computing all n2n^2 attention scores, sparse attention methods compute only a subset. Local windows, strided patterns, and learned sparsity can reduce complexity to O(nk)O(n \cdot k), where nn is the sequence length and knk \ll n is the number of positions each token attends to. For example, with a local window of 256 tokens, k=256k = 256 regardless of how long the sequence is, making the total cost linear in nn. 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

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 (QKT)V(QK^T)V, which requires the n×nn \times n intermediate matrix, linear attention computes Q(KTV)Q(K^TV). Since KTVK^TV has shape (d×d)(d \times d) rather than (n×n)(n \times n), the n2n^2 term disappears, achieving O(nd2)O(nd^2) complexity where dd 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.

Memory-Efficient Attention

FlashAttention and similar methods do not reduce asymptotic complexity but dramatically reduce memory consumption by restructuring the computation. Rather than materializing the full n×nn \times n 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.

Out[19]:
Visualization
Log-log plot comparing standard O(n^2) attention with sparse O(n*sqrt(n)) and linear O(n*d) attention, showing increasing divergence at longer sequences.
Complexity comparison of attention variants across a wide range of sequence lengths. Standard attention (red) scales quadratically, crossing into the trillions of operations by 64K tokens. Sparse and windowed attention grow much more slowly, remaining tractable at long sequences. Linear attention's cost depends on model dimension d rather than sequence length squared, crossing below standard attention at large n. Vertical dashed lines mark the context windows of landmark models.

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 O(nd2)O(nd^2) cost falls below the O(n2d)O(n^2 d) 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 O(nd)O(n \cdot d) 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 n2n^2 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 O(n2)O(n^2) 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 n2n^2 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 O(hn2bL)O(h \cdot n^2 \cdot b \cdot L) memory, where hh is the number of attention heads, bb is bytes per element, and LL is the number of layers. This often becomes the first constraint hit when extending context length.

  • Quadratic compute. The attention core requires O(n2d)O(n^2 d) operations per layer, dominated by two matrix multiplications: score computation (QKTQK^T) and output aggregation (AVAV). 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 O(n2)O(n^2) 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 n2n^2 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 n2n^2. Typical values range from 512 (early BERT) to 128K+ (modern long-context models). Even modest increases in nn 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 dd, making it far less impactful than sequence length.

  • h (number of heads): The number of parallel attention heads. Each head stores an independent n×nn \times n attention matrix, so memory scales linearly with hh. 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

Question 1 of 80 of 8 completed
If you double the sequence length from 2048 to 4096 tokens, how does the attention computation change?

Comments

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

Reference

Citation details

Cite or share this article.

BIBTEXAcademic
@misc{brenndoerfer2025quadraticattention, author = {Michael Brenndoerfer}, title = {Quadratic Attention Bottleneck}, year = {2025}, url = {https://mbrenndoerfer.com/writing/quadratic-attention-bottleneck-transformers-long-sequences}, organization = {mbrenndoerfer.com}, note = {Accessed: 2026-09-23} }
APAAcademic
Michael Brenndoerfer (2025). Quadratic Attention Bottleneck. Retrieved from https://mbrenndoerfer.com/writing/quadratic-attention-bottleneck-transformers-long-sequences
MLAAcademic
Michael Brenndoerfer. "Quadratic Attention Bottleneck." 2026. Web. September 23, 2026. <https://mbrenndoerfer.com/writing/quadratic-attention-bottleneck-transformers-long-sequences>.
CHICAGOAcademic
Michael Brenndoerfer. "Quadratic Attention Bottleneck." Accessed September 23, 2026. https://mbrenndoerfer.com/writing/quadratic-attention-bottleneck-transformers-long-sequences.
HARVARDAcademic
Michael Brenndoerfer (2025) 'Quadratic Attention Bottleneck'. Available at: https://mbrenndoerfer.com/writing/quadratic-attention-bottleneck-transformers-long-sequences (Accessed: September 23, 2026).
SimpleBasic
Michael Brenndoerfer (2025). Quadratic Attention Bottleneck. https://mbrenndoerfer.com/writing/quadratic-attention-bottleneck-transformers-long-sequences

About the author

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 Handbook
Newsletter

Stay up to date

Get articles, book updates, and news delivered to your inbox.

No spam, unsubscribe anytime.

or

Join the community

Sign in to remove popups, track your reading progress, and join the discussion.