Pratham Patel
· 53 min read

Hybrid Architectures: RetNet and the Three Computation Paradigms

Building RetNet from scratch — how a single retention formula admits three computation modes (parallel for training, recurrent for inference, chunkwise for long sequences) producing identical outputs, why exponential decay and complex-exponential position encoding together fix the two failure modes of linear attention, and what the impossible triangle of training parallelism, low-cost inference, and strong performance actually requires.

A hybrid architecture is one whose forward pass can be computed by more than one algorithm — a parallel one and a recurrent one — that produce identical outputs from the same parameters. Not approximations of each other. Not different models that happen to behave similarly. The same number, computed two ways. Such an architecture is neither a transformer nor an RNN; it is both, depending on which algorithm the implementation chooses to run.

This matters because of an old tension. Training a sequence model on a GPU rewards parallelism: every position should be computable at the same time. Generating tokens at inference rewards a constant-size state: every new token should cost the same regardless of how much context came before. Transformers nail the first but pay a growing KV cache for the second. RNNs nail the second but cannot parallelize across time. A model that admits both algorithms — train it as a parallel transformer, deploy it as an O(1)O(1) RNN — sidesteps the tradeoff entirely. Sun et al. (2023) call this the impossible triangle: training parallelism, low-cost inference, and strong performance, and argue that previous architectures achieved at most two of the three.

This post derives retention, the mechanism at the core of the Retentive Network (RetNet) and the cleanest worked example of the hybrid pattern. Retention has three computation modes — parallel (for training), recurrent (for inference), and chunkwise (for long sequences) — all dropping out of a single recurrence Sn=γSn1+knvnS_n = \gamma S_{n-1} + k_n v_n^\top. We will derive each mode, verify numerically that all three produce identical outputs, and then layer on the two pieces that make retention competitive with softmax attention: complex-exponential position encoding (which slots in via the eigendecomposition of a generalized state-transition matrix) and multi-scale retention (which assigns each head a different decay rate γ\gamma to capture different timescales).

The core paper is Sun et al. (2023), “Retentive Network: A Successor to Transformer for Large Language Models.”


The Running Example

We continue with the same tiny example from the Why Replace Attention blog:

  • n=4n = 4 tokens, dk=dv=2d_k = d_v = 2, single head

with the same query, key, and value matrices:

Q=(10011120),K=(01101102),V=(10011120)Q = \begin{pmatrix} 1 & 0 \\ 0 & 1 \\ 1 & 1 \\ 2 & 0 \end{pmatrix}, \quad K = \begin{pmatrix} 0 & 1 \\ 1 & 0 \\ 1 & 1 \\ 0 & 2 \end{pmatrix}, \quad V = \begin{pmatrix} 1 & 0 \\ 0 & 1 \\ 1 & 1 \\ 2 & 0 \end{pmatrix}

For the decay derivations, we fix:

γ=0.9\gamma = 0.9

This means each past token’s contribution to the state decays by a factor of 0.90.9 per step. A token 10 steps in the past has its influence scaled by 0.910=0.3490.9^{10} = 0.349 — roughly one-third of a token that just arrived.

For cost analysis, we use the same model parameters from the series:

  • dmodel=512d_\text{model} = 512, h=8h = 8 heads, dk=dv=64d_k = d_v = 64, L=12L = 12 layers, fp16

1. The Two Problems with Linear Attention’s Recurrence

1.1 Problem 1: Unbounded state accumulation

The Why Replace Attention blog derived the linear attention recurrence:

Si=Si1+ϕ(ki)vi,zi=zi1+ϕ(ki)S_i = S_{i-1} + \phi(k_i) \, v_i^\top, \qquad z_i = z_{i-1} + \phi(k_i)

Every token adds to the state. Nothing is ever forgotten. Let us trace what happens to the state matrix as tokens accumulate, using the linear attention values from the Why Replace Attention blog (with ϕ(x)=elu(x)+1\phi(x) = \text{elu}(x) + 1):

S1=(1020),S2=(1221),S3=(3443),S4=(54103)S_1 = \begin{pmatrix} 1 & 0 \\ 2 & 0 \end{pmatrix}, \qquad S_2 = \begin{pmatrix} 1 & 2 \\ 2 & 1 \end{pmatrix}, \qquad S_3 = \begin{pmatrix} 3 & 4 \\ 4 & 3 \end{pmatrix}, \qquad S_4 = \begin{pmatrix} 5 & 4 \\ 10 & 3 \end{pmatrix}

The entries of SS grow monotonically. To quantify this, we compute the Frobenius norm SF=i,jSij2\|S\|_F = \sqrt{\sum_{i,j} S_{ij}^2}, which measures the total magnitude of the state:

S1F=12+02+22+02=52.24\|S_1\|_F = \sqrt{1^2 + 0^2 + 2^2 + 0^2} = \sqrt{5} \approx 2.24 S2F=1+4+4+1=103.16\|S_2\|_F = \sqrt{1 + 4 + 4 + 1} = \sqrt{10} \approx 3.16 S3F=9+16+16+9=507.07\|S_3\|_F = \sqrt{9 + 16 + 16 + 9} = \sqrt{50} \approx 7.07 S4F=25+16+100+9=15012.25\|S_4\|_F = \sqrt{25 + 16 + 100 + 9} = \sqrt{150} \approx 12.25

The norm grew from 2.24 to 12.25 in just 4 tokens — a 5.5×5.5\times increase. For a sequence of nn tokens, each contributing an outer product of expected magnitude cc, the state norm grows as O(nc)O(n \cdot c). At n=128,000n = 128{,}000, the state entries become enormous. The numerical range of SS expands without bound, which creates two practical problems:

  1. Precision loss. In fp16 (the standard training precision), values above 65,504 overflow to infinity. Even before overflow, large values lose precision in the mantissa — small but important contributions from new tokens get rounded away when added to a large accumulated state.

  2. Old information dominates. Token 1’s contribution to SS is the same magnitude as token nn‘s, regardless of how far apart they are. In language modeling, a token 100,000 positions ago is almost certainly less relevant than a token 10 positions ago. But the accumulate-only recurrence treats them identically.

1.2 Problem 2: No position information

In standard softmax attention, the similarity exp(qikj/dk)\exp(q_i^\top k_j / \sqrt{d_k}) is typically augmented with position encodings — either absolute (Vaswani et al., 2017) or relative (Su et al., 2021). These encodings allow the model to distinguish “token jj is 3 positions before token ii” from “token jj is 300 positions before token ii.”

In linear attention, the kernel similarity ϕ(qi)ϕ(kj)\phi(q_i)^\top \phi(k_j) has no position dependence. The feature maps ϕ(qi)\phi(q_i) and ϕ(kj)\phi(k_j) depend only on the content of the query and key vectors, not on their positions ii and jj. The recurrent state Si=j=1iϕ(kj)vjS_i = \sum_{j=1}^i \phi(k_j) v_j^\top is a sum of outer products where each outer product carries no information about when it was added.

This means the model cannot learn position-dependent patterns like “the verb usually follows the subject within 5 tokens” or “the closing bracket matches the most recent opening bracket.” The decay factor in the normalization zi=j=1iϕ(kj)z_i = \sum_{j=1}^i \phi(k_j) is uniform across all positions — a crude tool that cannot distinguish distances.

1.3 What we need

We need two modifications to the linear attention recurrence:

  1. A forgetting mechanism that decays the contribution of old tokens, keeping the state bounded and prioritizing recent information.
  2. Position encoding that makes the query-key interaction depend on relative position (ij)(i - j), not just content.

RetNet achieves both. The forgetting mechanism is an exponential decay factor γ(0,1)\gamma \in (0, 1) applied to the state at every step. The position encoding comes from complex exponentials einθe^{i n \theta} that rotate the query and key vectors based on their absolute positions, producing a similarity that depends on relative position. We will derive each modification from scratch.


2. The Retention Recurrence

2.1 Adding decay

The simplest fix for unbounded accumulation is to multiply the old state by a scalar γ(0,1)\gamma \in (0, 1) at every step. This gives the retention recurrence:

Sn=γSn1+knvn\boxed{S_n = \gamma \, S_{n-1} + k_n \, v_n^\top} on=qnSno_n = q_n^\top \, S_n

where SnRdk×dvS_n \in \mathbb{R}^{d_k \times d_v} is the state matrix, knRdkk_n \in \mathbb{R}^{d_k} is the key vector for token nn, vnRdvv_n \in \mathbb{R}^{d_v} is the value vector, qnRdkq_n \in \mathbb{R}^{d_k} is the query vector, and onRdvo_n \in \mathbb{R}^{d_v} is the output. The initial state is S0=0S_0 = 0 (the zero matrix).

Compare this to the linear attention recurrence from the Why Replace Attention blog:

Snlinear=Sn1linear+ϕ(kn)vnS_n^{\text{linear}} = S_{n-1}^{\text{linear}} + \phi(k_n) \, v_n^\top

Two differences:

  1. The factor γ\gamma. The old state is scaled by γ\gamma before the new token’s contribution is added. When γ=1\gamma = 1, this reduces to linear attention’s accumulation (without the kernel). When γ<1\gamma < 1, older information exponentially decays.

  2. No kernel feature map. Retention uses the raw key vector knk_n, not a transformed version ϕ(kn)\phi(k_n). There is no elu+1 or any other kernel. This means the query-key product qnkmq_n^\top k_m can be negative — retention does not produce non-negative attention weights. The normalization comes from GroupNorm applied to the output (Section 8), not from a denominator like linear attention’s ϕ(qi)zi\phi(q_i)^\top z_i.

2.2 Unrolling the recurrence

Let us expand SnS_n by repeatedly substituting the recurrence. This is the technique of unrolling a recurrence relation — replacing each SiS_{i} with its definition in terms of Si1S_{i-1} until we reach the base case S0=0S_0 = 0.

Sn=γSn1+knvnS_n = \gamma \, S_{n-1} + k_n \, v_n^\top

Substitute Sn1=γSn2+kn1vn1S_{n-1} = \gamma \, S_{n-2} + k_{n-1} \, v_{n-1}^\top:

Sn=γ(γSn2+kn1vn1)+knvn=γ2Sn2+γkn1vn1+knvnS_n = \gamma (\gamma \, S_{n-2} + k_{n-1} \, v_{n-1}^\top) + k_n \, v_n^\top = \gamma^2 \, S_{n-2} + \gamma \, k_{n-1} \, v_{n-1}^\top + k_n \, v_n^\top

Substitute Sn2=γSn3+kn2vn2S_{n-2} = \gamma \, S_{n-3} + k_{n-2} \, v_{n-2}^\top:

Sn=γ3Sn3+γ2kn2vn2+γkn1vn1+knvnS_n = \gamma^3 \, S_{n-3} + \gamma^2 \, k_{n-2} \, v_{n-2}^\top + \gamma \, k_{n-1} \, v_{n-1}^\top + k_n \, v_n^\top

The pattern is clear. After nn substitutions, we reach S0=0S_0 = 0 and the γnS0\gamma^n S_0 term vanishes:

Sn=m=1nγnmkmvm\boxed{S_n = \sum_{m=1}^{n} \gamma^{n-m} \, k_m \, v_m^\top}

Each token mm contributes the outer product kmvmk_m v_m^\top, scaled by γnm\gamma^{n-m}. The exponent nmn - m is the distance from token mm to the current position nn.

The output for token nn is:

on=qnSn=qnm=1nγnmkmvm=m=1nγnm(qnkm)vmo_n = q_n^\top S_n = q_n^\top \sum_{m=1}^{n} \gamma^{n-m} \, k_m \, v_m^\top = \sum_{m=1}^{n} \gamma^{n-m} \, (q_n^\top k_m) \, v_m^\top

Since qnkmq_n^\top k_m is a scalar and vmv_m^\top is a row vector, we can write the output as a row vector:

on=m=1nγnm(qnkm)vm\boxed{o_n^\top = \sum_{m=1}^{n} \gamma^{n-m} \, (q_n^\top k_m) \, v_m^\top}

This says: the output for token nn is a weighted sum of all past value vectors v1,,vnv_1, \ldots, v_n. The weight on value vmv_m is the product of two factors: the content similarity qnkmq_n^\top k_m (how relevant is token mm to query nn?) and the decay γnm\gamma^{n-m} (how far away is token mm?).

2.3 What exponential decay means

The decay factor γnm\gamma^{n-m} is an exponentially decaying function of the distance nmn - m. Let us compute its values for γ=0.9\gamma = 0.9:

Distance nmn - mγnm\gamma^{n-m}Interpretation
00.90=1.0000.9^0 = 1.000Current token — full weight
10.91=0.9000.9^1 = 0.900Previous token — 90%
20.92=0.8100.9^2 = 0.8102 tokens ago — 81%
50.95=0.5900.9^5 = 0.5905 tokens ago — 59%
100.910=0.3490.9^{10} = 0.34910 tokens ago — 35%
500.950=0.00520.9^{50} = 0.005250 tokens ago — 0.5%
1000.9100=2.66×1050.9^{100} = 2.66 \times 10^{-5}100 tokens ago — negligible

With γ=0.9\gamma = 0.9, tokens more than 50 positions ago contribute less than 1% of their original weight. The model has a soft attention window: it can see all past tokens, but overwhelmingly focuses on recent ones.

The effective window size — the distance at which the decay drops to some threshold ϵ\epsilon — is:

γd=ϵ    d=logϵlogγ\gamma^{d} = \epsilon \implies d = \frac{\log \epsilon}{\log \gamma}

This follows by taking the natural logarithm of both sides and dividing. For γ=0.9\gamma = 0.9 and ϵ=0.01\epsilon = 0.01:

d=log0.01log0.9=4.6050.10543.7d = \frac{\log 0.01}{\log 0.9} = \frac{-4.605}{-0.105} \approx 43.7

So the effective window is about 44 tokens. The choice of γ\gamma controls the tradeoff between long-range and short-range attention. Higher γ\gamma (closer to 1) gives longer effective windows; lower γ\gamma gives shorter ones. RetNet uses different γ\gamma values for different heads — we will derive this in Section 7.

2.4 The bounded state property

Unlike linear attention, the retention state is bounded. Each entry of SnS_n is a sum of decaying contributions:

(Sn)ij=m=1nγnm(km)i(vm)j(S_n)_{ij} = \sum_{m=1}^{n} \gamma^{n-m} (k_m)_i (v_m)_j

Assuming each (km)i(vm)j(k_m)_i (v_m)_j is bounded by some constant cc, the sum is bounded by a geometric series:

(Sn)ijcm=1nγnm=cd=0n1γd=c1γn1γ|(S_n)_{ij}| \leq c \sum_{m=1}^{n} \gamma^{n-m} = c \sum_{d=0}^{n-1} \gamma^d = c \cdot \frac{1 - \gamma^n}{1 - \gamma}

The last equality uses the geometric series partial sum formula d=0N1γd=1γN1γ\sum_{d=0}^{N-1} \gamma^d = \frac{1 - \gamma^N}{1 - \gamma}.

As nn \to \infty, γn0\gamma^n \to 0 (since 0<γ<10 < \gamma < 1), so:

(Sn)ijc1γ|(S_n)_{ij}| \leq \frac{c}{1 - \gamma}

For γ=0.9\gamma = 0.9: c10.9=10c\frac{c}{1 - 0.9} = 10c. The state entries are bounded by 10 times the maximum single-token contribution. No matter how long the sequence, the state cannot grow beyond this bound. This is the bounded geometric series limit, and it eliminates the precision loss problem of linear attention.


3. Tracing the Retention Recurrence

3.1 Step-by-step computation

Let us trace the retention recurrence for all 4 tokens with γ=0.9\gamma = 0.9, using the raw QQ, KK, VV matrices (no kernel feature map).

Step n=1n = 1:

S1=γS0+k1v1=0.9×0+(01)(10)=(0010)S_1 = \gamma \cdot S_0 + k_1 v_1^\top = 0.9 \times 0 + \begin{pmatrix} 0 \\ 1 \end{pmatrix} \begin{pmatrix} 1 & 0 \end{pmatrix} = \begin{pmatrix} 0 & 0 \\ 1 & 0 \end{pmatrix} o1=q1S1=(10)(0010)=(00)o_1^\top = q_1^\top S_1 = \begin{pmatrix} 1 & 0 \end{pmatrix} \begin{pmatrix} 0 & 0 \\ 1 & 0 \end{pmatrix} = \begin{pmatrix} 0 & 0 \end{pmatrix}

Token 1 can only attend to itself. The query-key similarity is q1k1=(1)(0)+(0)(1)=0q_1^\top k_1 = (1)(0) + (0)(1) = 0 — query 1 and key 1 are orthogonal. In softmax attention, this would still produce a nonzero output (because exp(0)=1>0\exp(0) = 1 > 0). In retention, zero similarity means zero output. The GroupNorm applied later (Section 8) will handle the scaling.

Step n=2n = 2:

S2=0.9×(0010)+(10)(01)=(000.90)+(0100)=(010.90)S_2 = 0.9 \times \begin{pmatrix} 0 & 0 \\ 1 & 0 \end{pmatrix} + \begin{pmatrix} 1 \\ 0 \end{pmatrix} \begin{pmatrix} 0 & 1 \end{pmatrix} = \begin{pmatrix} 0 & 0 \\ 0.9 & 0 \end{pmatrix} + \begin{pmatrix} 0 & 1 \\ 0 & 0 \end{pmatrix} = \begin{pmatrix} 0 & 1 \\ 0.9 & 0 \end{pmatrix}

The old state S1S_1 was decayed by γ=0.9\gamma = 0.9. The entry (S1)21=1(S_1)_{21} = 1 (from token 1’s contribution) became 0.90.9 in S2S_2. Token 2’s contribution k2v2k_2 v_2^\top was added at full strength.

o2=q2S2=(01)(010.90)=(00+10.9    01+10)=(0.90)o_2^\top = q_2^\top S_2 = \begin{pmatrix} 0 & 1 \end{pmatrix} \begin{pmatrix} 0 & 1 \\ 0.9 & 0 \end{pmatrix} = \begin{pmatrix} 0 \cdot 0 + 1 \cdot 0.9 & \;\; 0 \cdot 1 + 1 \cdot 0 \end{pmatrix} = \begin{pmatrix} 0.9 & 0 \end{pmatrix}

Numerical check. We can verify this directly from the unrolled formula:

o2=γ1(q2k1)v1+γ0(q2k2)v2o_2^\top = \gamma^1 (q_2^\top k_1) v_1^\top + \gamma^0 (q_2^\top k_2) v_2^\top q2k1=(0)(0)+(1)(1)=1,q2k2=(0)(1)+(1)(0)=0q_2^\top k_1 = (0)(0) + (1)(1) = 1, \qquad q_2^\top k_2 = (0)(1) + (1)(0) = 0 o2=0.9×1×(1,0)+1×0×(0,1)=(0.9,0)+(0,0)=(0.9,0)o_2^\top = 0.9 \times 1 \times (1, 0) + 1 \times 0 \times (0, 1) = (0.9, 0) + (0, 0) = (0.9, 0) \quad \checkmark

Token 2 attends to token 1 with similarity 1, decayed by γ1=0.9\gamma^1 = 0.9. It attends to itself with similarity 0. So the output is dominated by token 1’s value vector.

Step n=3n = 3:

S3=0.9×(010.90)+(11)(11)=(00.90.810)+(1111)=(11.91.811)S_3 = 0.9 \times \begin{pmatrix} 0 & 1 \\ 0.9 & 0 \end{pmatrix} + \begin{pmatrix} 1 \\ 1 \end{pmatrix} \begin{pmatrix} 1 & 1 \end{pmatrix} = \begin{pmatrix} 0 & 0.9 \\ 0.81 & 0 \end{pmatrix} + \begin{pmatrix} 1 & 1 \\ 1 & 1 \end{pmatrix} = \begin{pmatrix} 1 & 1.9 \\ 1.81 & 1 \end{pmatrix}

Notice that the entry (S1)21=1(S_1)_{21} = 1 from token 1 has now decayed to 0.81=0.92=γ20.81 = 0.9^2 = \gamma^2, exactly as predicted by the formula γnm=γ31=0.81\gamma^{n-m} = \gamma^{3-1} = 0.81.

o3=q3S3=(11)(11.91.811)=(1+1.81    1.9+1)=(2.812.9)o_3^\top = q_3^\top S_3 = \begin{pmatrix} 1 & 1 \end{pmatrix} \begin{pmatrix} 1 & 1.9 \\ 1.81 & 1 \end{pmatrix} = \begin{pmatrix} 1 + 1.81 & \;\; 1.9 + 1 \end{pmatrix} = \begin{pmatrix} 2.81 & 2.9 \end{pmatrix}

Step n=4n = 4:

S4=0.9×(11.91.811)+(02)(20)=(0.91.711.6290.9)+(0040)=(0.91.715.6290.9)S_4 = 0.9 \times \begin{pmatrix} 1 & 1.9 \\ 1.81 & 1 \end{pmatrix} + \begin{pmatrix} 0 \\ 2 \end{pmatrix} \begin{pmatrix} 2 & 0 \end{pmatrix} = \begin{pmatrix} 0.9 & 1.71 \\ 1.629 & 0.9 \end{pmatrix} + \begin{pmatrix} 0 & 0 \\ 4 & 0 \end{pmatrix} = \begin{pmatrix} 0.9 & 1.71 \\ 5.629 & 0.9 \end{pmatrix} o4=q4S4=(20)(0.91.715.6290.9)=(1.83.42)o_4^\top = q_4^\top S_4 = \begin{pmatrix} 2 & 0 \end{pmatrix} \begin{pmatrix} 0.9 & 1.71 \\ 5.629 & 0.9 \end{pmatrix} = \begin{pmatrix} 1.8 & 3.42 \end{pmatrix}

3.2 Summary of outputs

Token nnono_n^\top
1(0,  0)(0, \; 0)
2(0.9,  0)(0.9, \; 0)
3(2.81,  2.9)(2.81, \; 2.9)
4(1.8,  3.42)(1.8, \; 3.42)

3.3 State norm comparison

S1F=1.00,S2F=0+1+0.81+0=1.811.35\|S_1\|_F = 1.00, \quad \|S_2\|_F = \sqrt{0 + 1 + 0.81 + 0} = \sqrt{1.81} \approx 1.35 S3F=1+3.61+3.276+1=8.8862.98\|S_3\|_F = \sqrt{1 + 3.61 + 3.276 + 1} = \sqrt{8.886} \approx 2.98 S4F=0.81+2.924+31.686+0.81=36.236.02\|S_4\|_F = \sqrt{0.81 + 2.924 + 31.686 + 0.81} = \sqrt{36.23} \approx 6.02

Compare to the linear attention state norms (from Section 1.1): 2.243.167.0712.252.24 \to 3.16 \to 7.07 \to 12.25. The retention state norms are: 1.001.352.986.021.00 \to 1.35 \to 2.98 \to 6.02. The retention state is growing more slowly because the decay factor γ=0.9\gamma = 0.9 shrinks old contributions at every step. For long sequences, the retention state converges to a bounded value while the linear attention state grows without bound.


4. The Parallel Form

4.1 From recurrence to matrix form

The recurrent form is ideal for inference (one token at a time), but it is sequential — SnS_n depends on Sn1S_{n-1}, which depends on Sn2S_{n-2}, and so on. During training, we process the entire sequence at once and need a parallel computation.

We already derived the unrolled output:

on=m=1nγnm(qnkm)vmo_n^\top = \sum_{m=1}^{n} \gamma^{n-m} (q_n^\top k_m) \, v_m^\top

This is a weighted combination of value vectors. The weight on vmv_m is:

wnm=γnm(qnkm)for mn,wnm=0for m>nw_{nm} = \gamma^{n-m} (q_n^\top k_m) \quad \text{for } m \leq n, \qquad w_{nm} = 0 \quad \text{for } m > n

The first factor qnkmq_n^\top k_m is the (n,m)(n, m) entry of the matrix QKQK^\top. The second factor γnm\gamma^{n-m} is a function of the distance nmn - m only, and is zero for m>nm > n (causal masking). We can write this as a single matrix.

4.2 The DD matrix

Define the decay matrix DRn×nD \in \mathbb{R}^{n \times n} as:

Dnm={γnmif nm0if n<m\boxed{D_{nm} = \begin{cases} \gamma^{n-m} & \text{if } n \geq m \\ 0 & \text{if } n < m \end{cases}}

This matrix combines two things into one: causal masking (the zero entries above the diagonal ensure token nn cannot attend to future tokens m>nm > n) and exponential decay (the entry γnm\gamma^{n-m} weights past tokens by their distance).

For our running example with n=4n = 4 and γ=0.9\gamma = 0.9:

D=(10000.91000.810.9100.7290.810.91)D = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0.9 & 1 & 0 & 0 \\ 0.81 & 0.9 & 1 & 0 \\ 0.729 & 0.81 & 0.9 & 1 \end{pmatrix}

The diagonal is all 1’s (each token attends to itself with no decay). The first column decays as 1,0.9,0.81,0.7291, 0.9, 0.81, 0.729 — token 1’s influence fades as we move forward. The upper triangle is all zeros — no future peeking.

Compare this to the standard causal mask in softmax attention, which is:

M=(1000110011101111)M = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 1 & 1 & 0 & 0 \\ 1 & 1 & 1 & 0 \\ 1 & 1 & 1 & 1 \end{pmatrix}

The standard mask uses 1 for all allowed positions — no decay. DD is a generalization: it is a causal mask where the allowed entries are weighted by exponential decay instead of being uniformly 1. When γ=1\gamma = 1, DD reduces to MM.

4.3 The parallel retention formula

The full parallel computation is:

Retention(X)=(QKD)V\boxed{\text{Retention}(X) = (QK^\top \odot D) \, V}

where \odot is the Hadamard product (element-wise multiplication, defined in the Gated Attention blog). This says: compute the n×nn \times n query-key similarity matrix QKQK^\top, multiply it element-wise by the decay matrix DD (which simultaneously applies causal masking and exponential decay), then multiply by the value matrix VV.

4.4 Numerical verification

Let us compute the parallel form and verify it matches the recurrent outputs from Section 3.

Step 1: Compute QKQK^\top.

QK=(10011120)(01101012)QK^\top = \begin{pmatrix} 1 & 0 \\ 0 & 1 \\ 1 & 1 \\ 2 & 0 \end{pmatrix} \begin{pmatrix} 0 & 1 & 1 & 0 \\ 1 & 0 & 1 & 2 \end{pmatrix}

Row 1: (10+01,  11+00,  11+01,  10+02)=(0,1,1,0)(1 \cdot 0 + 0 \cdot 1, \; 1 \cdot 1 + 0 \cdot 0, \; 1 \cdot 1 + 0 \cdot 1, \; 1 \cdot 0 + 0 \cdot 2) = (0, 1, 1, 0)

Row 2: (00+11,  01+10,  01+11,  00+12)=(1,0,1,2)(0 \cdot 0 + 1 \cdot 1, \; 0 \cdot 1 + 1 \cdot 0, \; 0 \cdot 1 + 1 \cdot 1, \; 0 \cdot 0 + 1 \cdot 2) = (1, 0, 1, 2)

Row 3: (10+11,  11+10,  11+11,  10+12)=(1,1,2,2)(1 \cdot 0 + 1 \cdot 1, \; 1 \cdot 1 + 1 \cdot 0, \; 1 \cdot 1 + 1 \cdot 1, \; 1 \cdot 0 + 1 \cdot 2) = (1, 1, 2, 2)

Row 4: (20+01,  21+00,  21+01,  20+02)=(0,2,2,0)(2 \cdot 0 + 0 \cdot 1, \; 2 \cdot 1 + 0 \cdot 0, \; 2 \cdot 1 + 0 \cdot 1, \; 2 \cdot 0 + 0 \cdot 2) = (0, 2, 2, 0)

QK=(0110101211220220)QK^\top = \begin{pmatrix} 0 & 1 & 1 & 0 \\ 1 & 0 & 1 & 2 \\ 1 & 1 & 2 & 2 \\ 0 & 2 & 2 & 0 \end{pmatrix}

Step 2: Apply DD via Hadamard product.

QKD=(0110101211220220)(10000.91000.810.9100.7290.810.91)QK^\top \odot D = \begin{pmatrix} 0 & 1 & 1 & 0 \\ 1 & 0 & 1 & 2 \\ 1 & 1 & 2 & 2 \\ 0 & 2 & 2 & 0 \end{pmatrix} \odot \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0.9 & 1 & 0 & 0 \\ 0.81 & 0.9 & 1 & 0 \\ 0.729 & 0.81 & 0.9 & 1 \end{pmatrix}

Row 1: (01,  10,  10,  00)=(0,0,0,0)(0 \cdot 1, \; 1 \cdot 0, \; 1 \cdot 0, \; 0 \cdot 0) = (0, 0, 0, 0)

Row 2: (10.9,  01,  10,  20)=(0.9,0,0,0)(1 \cdot 0.9, \; 0 \cdot 1, \; 1 \cdot 0, \; 2 \cdot 0) = (0.9, 0, 0, 0)

Row 3: (10.81,  10.9,  21,  20)=(0.81,0.9,2,0)(1 \cdot 0.81, \; 1 \cdot 0.9, \; 2 \cdot 1, \; 2 \cdot 0) = (0.81, 0.9, 2, 0)

Row 4: (00.729,  20.81,  20.9,  01)=(0,1.62,1.8,0)(0 \cdot 0.729, \; 2 \cdot 0.81, \; 2 \cdot 0.9, \; 0 \cdot 1) = (0, 1.62, 1.8, 0)

QKD=(00000.90000.810.92001.621.80)QK^\top \odot D = \begin{pmatrix} 0 & 0 & 0 & 0 \\ 0.9 & 0 & 0 & 0 \\ 0.81 & 0.9 & 2 & 0 \\ 0 & 1.62 & 1.8 & 0 \end{pmatrix}

This is the retention matrix — the analog of the attention weight matrix in softmax attention. But unlike softmax attention weights, these entries are not normalized to sum to 1, and they can be negative (though in this example they happen to be non-negative because all qnkmq_n^\top k_m are non-negative for our particular QQ and KK).

Step 3: Multiply by VV.

(QKD)V=(00000.90000.810.92001.621.80)(10011120)(QK^\top \odot D) \, V = \begin{pmatrix} 0 & 0 & 0 & 0 \\ 0.9 & 0 & 0 & 0 \\ 0.81 & 0.9 & 2 & 0 \\ 0 & 1.62 & 1.8 & 0 \end{pmatrix} \begin{pmatrix} 1 & 0 \\ 0 & 1 \\ 1 & 1 \\ 2 & 0 \end{pmatrix}

Row 1: 0(1,0)+0(0,1)+0(1,1)+0(2,0)=(0,0)0 \cdot (1, 0) + 0 \cdot (0, 1) + 0 \cdot (1, 1) + 0 \cdot (2, 0) = (0, 0)

Row 2: 0.9(1,0)+0(0,1)+0(1,1)+0(2,0)=(0.9,0)0.9 \cdot (1, 0) + 0 \cdot (0, 1) + 0 \cdot (1, 1) + 0 \cdot (2, 0) = (0.9, 0)

Row 3: 0.81(1,0)+0.9(0,1)+2(1,1)+0(2,0)=(0.81+2,  0.9+2)=(2.81,2.9)0.81 \cdot (1, 0) + 0.9 \cdot (0, 1) + 2 \cdot (1, 1) + 0 \cdot (2, 0) = (0.81 + 2, \; 0.9 + 2) = (2.81, 2.9)

Row 4: 0(1,0)+1.62(0,1)+1.8(1,1)+0(2,0)=(1.8,  1.62+1.8)=(1.8,3.42)0 \cdot (1, 0) + 1.62 \cdot (0, 1) + 1.8 \cdot (1, 1) + 0 \cdot (2, 0) = (1.8, \; 1.62 + 1.8) = (1.8, 3.42)

Retention(X)=(000.902.812.91.83.42)\text{Retention}(X) = \begin{pmatrix} 0 & 0 \\ 0.9 & 0 \\ 2.81 & 2.9 \\ 1.8 & 3.42 \end{pmatrix}

Verification: Compare each row with the recurrent outputs from Section 3.2:

TokenRecurrent ono_n^\topParallel row nnMatch?
1(0,0)(0, 0)(0,0)(0, 0)\checkmark
2(0.9,0)(0.9, 0)(0.9,0)(0.9, 0)\checkmark
3(2.81,2.9)(2.81, 2.9)(2.81,2.9)(2.81, 2.9)\checkmark
4(1.8,3.42)(1.8, 3.42)(1.8,3.42)(1.8, 3.42)\checkmark

Both forms produce identical outputs. The parallel form computed everything at once using matrix operations. The recurrent form computed outputs one at a time using state updates. The mathematics guarantees they are equivalent.


5. The Hybrid Architecture: One Formula, Multiple Computation Modes

This is the defining section of this blog. Everything we have derived so far leads here: the retention formula is a single mathematical object that can be computed in fundamentally different ways depending on the context. This is what makes RetNet a hybrid architecture — not a transformer, not an RNN, but a single model that computes as a transformer during training and as an RNN during inference, with exact equivalence.

5.1 Training uses the parallel form

During training, the full sequence is available. The parallel form Retention(X)=(QKD)V\text{Retention}(X) = (QK^\top \odot D) V is a sequence of matrix multiplications and a Hadamard product — operations that GPUs execute efficiently in parallel. The cost is:

  • QKQK^\top: (n×dk)×(dk×n)=O(n2dk)(n \times d_k) \times (d_k \times n) = O(n^2 d_k)
  • Hadamard product with DD: O(n2)O(n^2)
  • Multiply by VV: (n×n)×(n×dv)=O(n2dv)(n \times n) \times (n \times d_v) = O(n^2 d_v)

Total: O(n2dk)O(n^2 d_k) per head. This is the same asymptotic cost as softmax attention. The advantage is not in the asymptotic complexity — it is in the simplicity. There is no softmax (which requires a sequential max-subtraction for numerical stability), no exponential, no normalization denominator. Just matrix multiply, Hadamard product, matrix multiply.

5.2 Inference uses the recurrent form

During autoregressive generation, we process one token at a time. The recurrent form Sn=γSn1+knvnS_n = \gamma S_{n-1} + k_n v_n^\top, on=qnSno_n = q_n^\top S_n has:

  • State size: dk×dvd_k \times d_v per head. With dk=dv=64d_k = d_v = 64: 64×64=4,09664 \times 64 = 4{,}096 elements per head. Across h=8h = 8 heads and L=12L = 12 layers, in fp16: 8×12×4,096×2=786,4328 \times 12 \times 4{,}096 \times 2 = 786{,}432 bytes 0.75\approx 0.75 MB.

  • Compute per token: One scalar-matrix multiply (γSn1\gamma S_{n-1}: O(dkdv)O(d_k d_v)), one outer product (knvnk_n v_n^\top: O(dkdv)O(d_k d_v)), one matrix-vector product (qnSnq_n^\top S_n: O(dkdv)O(d_k d_v)). Total: O(dkdv)=O(dk2)O(d_k d_v) = O(d_k^2) per head.

Both are constant — independent of how many tokens have been generated. Compare to softmax attention, where the KV cache grows as O(ndk)O(n \cdot d_k) per head and the compute per token grows as O(ndk)O(n \cdot d_k):

PropertySoftmax attentionRetention (recurrent)
State per head at step nn2ndk2n \cdot d_k elements (KV cache)dk×dvd_k \times d_v elements (constant)
Compute per token at step nnO(ndk)O(n \cdot d_k) (grows)O(dk2)O(d_k^2) (constant)
State at n=128,000n = 128{,}000, our model3.15 GB0.75 MB

The recurrent retention state is 4,200×4{,}200\times smaller than the KV cache at 128K tokens.

5.3 The impossible triangle and why hybrid architectures matter

The parallel and recurrent forms compute the same function. This is the core property of a hybrid architecture: you choose the computation mode based on the hardware context, not the mathematical definition. Training uses the parallel form because GPUs are parallel processors. Inference uses the recurrent form because autoregressive generation is inherently sequential. The same weights, the same function, different execution strategies.

Before hybrid architectures, the field was stuck in a tradeoff. Sun et al. (2023) call it the impossible triangle: training parallelism, low-cost inference, and strong performance. Every architecture achieved at most two of the three:

ArchitectureTraining parallelismO(1)O(1) inferenceStrong performance
Transformer\checkmark×\times\checkmark\checkmark
Linear Transformer\checkmark\checkmark×\times
Recurrent NN×\times\checkmark×\times
RWKV×\times\checkmark\checkmark
H3/S4\checkmark\checkmark\checkmark
Hyena\checkmarkO(n)O(n)\checkmark
RetNet\checkmark\checkmark\checkmark\checkmark

RetNet claims all three vertices of the triangle. The rest of this blog derives the additional components — position encoding, chunkwise computation, multi-scale heads, and gating — that make this possible.


6. Position Encoding via Complex Exponentials

6.1 The problem

The retention formula on=m=1nγnm(qnkm)vmo_n^\top = \sum_{m=1}^n \gamma^{n-m} (q_n^\top k_m) v_m^\top has a position-dependent factor (γnm\gamma^{n-m}, which depends on the distance), but the query-key interaction qnkmq_n^\top k_m depends only on the content of qnq_n and kmk_m, not on their positions nn and mm.

Consider two scenarios:

  • Query at position 10, key at position 8: q10k8q_{10}^\top k_8 with decay γ2\gamma^2
  • Query at position 1000, key at position 998: q1000k998q_{1000}^\top k_{998} with decay γ2\gamma^2

If q10=q1000q_{10} = q_{1000} and k8=k998k_8 = k_{998} (same content), both scenarios produce the same output. The model cannot learn that position-dependent patterns like “subject-verb agreement” work differently at the start vs the middle of a document. The decay factor provides only a distance-based weighting, not a full relative position encoding.

6.2 The general state transition matrix

The fix has to come from the recurrence itself. The scalar decay γ\gamma shrinks the state by the same fraction at every step regardless of position, which is why nothing in the formula knows where token mm sits on the timeline. Replace that single number with a d×dd \times d matrix and the per-step transformation becomes rich enough to encode rotation in addition to decay — the rotation will carry the position information.

Concretely, generalize the recurrence by replacing the scalar γ\gamma with a state-transition matrix ARd×dA \in \mathbb{R}^{d \times d}:

sn=Asn1+knvns_n = A \, s_{n-1} + k_n \, v_n^\top

Unrolling this gives:

sn=m=1nAnmkmvms_n = \sum_{m=1}^{n} A^{n-m} \, k_m \, v_m^\top

The output is:

on=qnsn=m=1nqnAnmkmvmo_n = q_n^\top s_n = \sum_{m=1}^{n} q_n^\top A^{n-m} k_m \, v_m^\top

Now AnmA^{n-m} is a d×dd \times d matrix raised to the power (nm)(n-m). Computing AnmA^{n-m} directly is expensive — matrix exponentiation costs O(d3log(nm))O(d^3 \log(n-m)). But if we diagonalize AA, the computation simplifies dramatically.

6.3 Diagonalizing AA

By the eigendecomposition theorem, if AA has dd linearly independent eigenvectors, we can write:

A=Λdiag(λ1,,λd)Λ1A = \Lambda \, \text{diag}(\lambda_1, \ldots, \lambda_d) \, \Lambda^{-1}

where Λ\Lambda is the matrix of eigenvectors (columns are eigenvectors) and λ1,,λd\lambda_1, \ldots, \lambda_d are the eigenvalues. The notation diag(λ1,,λd)\text{diag}(\lambda_1, \ldots, \lambda_d) denotes the diagonal matrix with λi\lambda_i on the ii-th diagonal entry.

The key property of the eigendecomposition is that matrix powers become trivial:

Anm=Λdiag(λ1nm,,λdnm)Λ1A^{n-m} = \Lambda \, \text{diag}(\lambda_1^{n-m}, \ldots, \lambda_d^{n-m}) \, \Lambda^{-1}

This follows because A2=(ΛDλΛ1)(ΛDλΛ1)=ΛDλ(Λ1Λ)DλΛ1=ΛDλ2Λ1A^2 = (\Lambda D_\lambda \Lambda^{-1})(\Lambda D_\lambda \Lambda^{-1}) = \Lambda D_\lambda ({\Lambda^{-1} \Lambda}) D_\lambda \Lambda^{-1} = \Lambda D_\lambda^2 \Lambda^{-1}, where the Λ1Λ=I\Lambda^{-1} \Lambda = I cancellation in the middle is the crucial step. By induction, Ak=ΛDλkΛ1A^k = \Lambda D_\lambda^k \Lambda^{-1}, and Dλk=diag(λ1k,,λdk)D_\lambda^k = \text{diag}(\lambda_1^k, \ldots, \lambda_d^k) because powers of a diagonal matrix are diagonal with powered entries.

6.4 Absorbing Λ\Lambda into the projections

Substituting the eigendecomposition into the output:

on=m=1nqnΛdiag(λinm)Λ1kmvmo_n^\top = \sum_{m=1}^{n} q_n^\top \Lambda \, \text{diag}(\lambda_i^{n-m}) \, \Lambda^{-1} k_m \, v_m^\top

Define new query and key vectors that absorb the eigenvector matrices:

q~n=qnΛ,k~m=Λ1km\tilde{q}_n^\top = q_n^\top \Lambda, \qquad \tilde{k}_m = \Lambda^{-1} k_m

Since qn=WQxnq_n = W_Q^\top x_n and km=WKxmk_m = W_K^\top x_m for learned projection matrices WQ,WKW_Q, W_K, absorbing Λ\Lambda into the projections means defining:

W~Q=WQΛ,W~K=(Λ1)WK\tilde{W}_Q = W_Q \Lambda, \qquad \tilde{W}_K = (\Lambda^{-1})^\top W_K

These are just different learned matrices. Since WQW_Q and WKW_K are learned from data, absorbing Λ\Lambda changes nothing about the model’s expressivity — the optimizer will find appropriate values for W~Q\tilde{W}_Q and W~K\tilde{W}_K. After this absorption:

on=m=1nq~ndiag(λinm)k~mvmo_n^\top = \sum_{m=1}^{n} \tilde{q}_n^\top \, \text{diag}(\lambda_i^{n-m}) \, \tilde{k}_m \, v_m^\top

The matrix diag(λinm)\text{diag}(\lambda_i^{n-m}) is diagonal, so the product q~ndiag(λinm)k~m\tilde{q}_n^\top \, \text{diag}(\lambda_i^{n-m}) \, \tilde{k}_m can be written element-wise:

q~ndiag(λinm)k~m=p=1d(q~n)pλpnm(k~m)p\tilde{q}_n^\top \, \text{diag}(\lambda_i^{n-m}) \, \tilde{k}_m = \sum_{p=1}^{d} (\tilde{q}_n)_p \, \lambda_p^{n-m} \, (\tilde{k}_m)_p

This is a sum of dd terms, each involving one eigenvalue λp\lambda_p.

6.5 Choosing eigenvalues: γeiθ\gamma e^{i\theta}

RetNet chooses the eigenvalues to be complex numbers of the form:

λp=γeiθp\lambda_p = \gamma \, e^{i \theta_p}

where γ(0,1)\gamma \in (0, 1) is a scalar (the same decay rate for all dimensions within a head) and θpR\theta_p \in \mathbb{R} is a different angle for each dimension pp. The notation eiθe^{i\theta} is Euler’s formula: eiθ=cosθ+isinθe^{i\theta} = \cos\theta + i \sin\theta, where i=1i = \sqrt{-1} is the imaginary unit.

Why this specific form? Because it separates two functions:

  1. The magnitude γ\gamma controls decay. Since λp=γeiθp=γeiθp=γ1=γ|\lambda_p| = |\gamma e^{i\theta_p}| = \gamma \cdot |e^{i\theta_p}| = \gamma \cdot 1 = \gamma, the magnitude of each eigenvalue is γ\gamma. This means λpnm=γnm|\lambda_p^{n-m}| = \gamma^{n-m} — exponential decay with distance, exactly as before.

  2. The phase eiθpe^{i\theta_p} controls rotation. The factor ei(nm)θpe^{i(n-m)\theta_p} depends on the distance nmn - m and the dimension-specific angle θp\theta_p. Different dimensions rotate at different frequencies, creating a rich encoding of relative position.

The power λpnm\lambda_p^{n-m} factors as:

λpnm=(γeiθp)nm=γnmei(nm)θp\lambda_p^{n-m} = (\gamma e^{i\theta_p})^{n-m} = \gamma^{n-m} \, e^{i(n-m)\theta_p}

This is the product of a decay term (real, positive, decreasing) and a rotation term (complex, unit magnitude, oscillating).

6.6 The factored form

We can further factor the position-dependent term. Since γ\gamma is a scalar (same for all dimensions):

λpnm=γnmei(nm)θp=γnmeinθpeimθp\lambda_p^{n-m} = \gamma^{n-m} \, e^{i(n-m)\theta_p} = \gamma^{n-m} \, e^{in\theta_p} \, e^{-im\theta_p}

The last step uses the exponential product rule ea+b=eaebe^{a+b} = e^a e^b, applied to ei(nm)θp=einθpimθp=einθpeimθpe^{i(n-m)\theta_p} = e^{in\theta_p - im\theta_p} = e^{in\theta_p} e^{-im\theta_p}.

Substituting into the output:

on=m=1nγnm(p=1d(q~n)peinθp(k~m)peimθp)vmo_n^\top = \sum_{m=1}^{n} \gamma^{n-m} \left(\sum_{p=1}^{d} (\tilde{q}_n)_p \, e^{in\theta_p} \cdot (\tilde{k}_m)_p \, e^{-im\theta_p}\right) v_m^\top

Define position-encoded queries and keys:

(Qn)p=(q~n)peinθp,(Km)p=(k~m)peimθp(Q_n)_p = (\tilde{q}_n)_p \, e^{in\theta_p}, \qquad (K_m)_p = (\tilde{k}_m)_p \, e^{-im\theta_p}

In vector notation, using \odot for element-wise multiplication:

Qn=q~nΘn,Km=k~mΘˉm\boxed{Q_n = \tilde{q}_n \odot \Theta_n, \qquad K_m = \tilde{k}_m \odot \bar{\Theta}_m}

where Θn=(einθ1,einθ2,,einθd)\Theta_n = (e^{in\theta_1}, e^{in\theta_2}, \ldots, e^{in\theta_d}) and Θˉm=(eimθ1,eimθ2,,eimθd)\bar{\Theta}_m = (e^{-im\theta_1}, e^{-im\theta_2}, \ldots, e^{-im\theta_d}) is its complex conjugate (the complex conjugate of eiαe^{i\alpha} is eiαe^{-i\alpha}).

Then the inner sum becomes:

p=1d(Qn)p(Km)p=QnKm\sum_{p=1}^{d} (Q_n)_p \cdot (K_m)_p = Q_n^\top K_m

where the transpose here is the regular transpose (not conjugate transpose), because the conjugation is already built into KmK_m through Θˉm\bar{\Theta}_m.

The full output is:

on=m=1nγnm(QnKm)vmo_n^\top = \sum_{m=1}^{n} \gamma^{n-m} (Q_n^\top K_m) \, v_m^\top

This has exactly the same form as Section 2.2, but now QnQ_n and KmK_m carry position information through the complex exponential factors. The parallel form becomes:

Retention(X)=(QKD)V\boxed{\text{Retention}(X) = (QK^\top \odot D) \, V}

with the position-encoded Q=(XWQ)ΘQ = (XW_Q) \odot \Theta, K=(XWK)ΘˉK = (XW_K) \odot \bar{\Theta}, V=XWVV = XW_V, and Dnm=γnmD_{nm} = \gamma^{n-m} for nmn \geq m, zero otherwise.

6.7 The relative position property

This is the crucial observation. The product QnKmQ_n^\top K_m expands as:

QnKm=p=1d(q~n)peinθp(k~m)peimθp=p=1d(q~n)p(k~m)pei(nm)θpQ_n^\top K_m = \sum_{p=1}^{d} (\tilde{q}_n)_p \, e^{in\theta_p} \cdot (\tilde{k}_m)_p \, e^{-im\theta_p} = \sum_{p=1}^{d} (\tilde{q}_n)_p \, (\tilde{k}_m)_p \, e^{i(n-m)\theta_p}

The complex exponential ei(nm)θpe^{i(n-m)\theta_p} depends only on the relative position nmn - m, not on the absolute positions nn and mm separately. This is precisely the property of relative position encodings like RoPE (Su et al., 2021) and xPos (Sun et al., 2022). The RetNet paper notes that this formulation is equivalent to xPos — the same mechanism proposed for length-extrapolatable transformers, here derived naturally from the eigendecomposition of the state transition matrix.

6.8 Practical implementation

In practice, the complex arithmetic is implemented using real numbers. For each pair of consecutive dimensions (2p,2p+1)(2p, 2p+1), the rotation ei(nm)θpe^{i(n-m)\theta_p} is applied as a 2×22 \times 2 rotation matrix:

(cos((nm)θp)sin((nm)θp)sin((nm)θp)cos((nm)θp))\begin{pmatrix} \cos((n-m)\theta_p) & -\sin((n-m)\theta_p) \\ \sin((n-m)\theta_p) & \cos((n-m)\theta_p) \end{pmatrix}

This is the standard technique used by RoPE and xPos: pair up dimensions, rotate each pair by an angle proportional to the position, and different pairs use different base frequencies θp\theta_p.

6.9 Numerical example: position encoding effect

To see the effect concretely, consider a single dimension pair with θ=π/4\theta = \pi/4. For query at position n=4n = 4 and keys at positions m=1,2,3,4m = 1, 2, 3, 4:

Distance nmn - mei(nm)θe^{i(n-m)\theta}cos((nm)π/4)\cos((n-m)\pi/4)sin((nm)π/4)\sin((n-m)\pi/4)
3ei3π/4e^{i \cdot 3\pi/4}0.707-0.7070.7070.707
2ei2π/4e^{i \cdot 2\pi/4}0011
1eiπ/4e^{i \cdot \pi/4}0.7070.7070.7070.707
0ei0e^{i \cdot 0}1100

The rotation factor oscillates with distance. A key 3 positions away gets its first dimension component flipped in sign (cos(3π/4)=0.707\cos(3\pi/4) = -0.707), while a key 1 position away gets a positive contribution (cos(π/4)=0.707\cos(\pi/4) = 0.707). Combined with the decay γnm\gamma^{n-m}, this creates a rich position-dependent similarity landscape: the model can learn to prefer keys at specific relative positions, not just nearby keys.


7. The Chunkwise Recurrent Form

7.1 The motivation

The parallel form has cost O(n2dk)O(n^2 d_k) — good for moderate sequences, but quadratic in nn. The recurrent form has cost O(ndk2)O(n d_k^2) — linear in nn, but sequential (each step depends on the previous state). For long sequences during training, we want the best of both: parallel computation where possible, sequential state passing where necessary.

The chunkwise recurrent form divides the sequence into chunks of size BB. Within each chunk, retention is computed in parallel using the parallel form. Across chunks, the state is passed recurrently. This gives:

  • Parallelism within each chunk (GPU-efficient)
  • Linear memory across chunks (no O(n2)O(n^2) matrix)
  • Total cost: O(ndk(B+dk))O(n \cdot d_k \cdot (B + d_k)) — when BB and dkd_k are much smaller than nn, this is linear in nn

7.2 Derivation

Consider chunk [i][i] containing tokens (i1)B+1(i-1)B + 1 through iBiB. For notational simplicity, we write Q[i],K[i],V[i]Q_{[i]}, K_{[i]}, V_{[i]} for the query, key, and value matrices restricted to this chunk (each is B×dB \times d).

The output for a token at position nn within chunk [i][i] has two parts:

  1. Inner-chunk: Attention to other tokens within the same chunk. This uses the parallel form restricted to the chunk: (Q[i]K[i]Dchunk)V[i](Q_{[i]} K_{[i]}^\top \odot D_\text{chunk}) V_{[i]}, where DchunkD_\text{chunk} is the B×BB \times B decay matrix for positions within the chunk.

  2. Cross-chunk: Attention to all tokens in previous chunks, summarized by the recurrent state Ri1R_{i-1}.

The cross-chunk contribution for token at position jj (1-indexed) within chunk [i][i] is:

crossj=γjqjRi1\text{cross}_j = \gamma^j \cdot q_j^\top R_{i-1}

where γj\gamma^j accounts for the decay from the end of the previous chunk to position jj within the current chunk. In matrix form:

Cross-chunk=(Q[i]Ri1)ξ\text{Cross-chunk} = (Q_{[i]} R_{i-1}) \odot \xi

where ξ\xi is a column vector (γ1,γ2,,γB)(\gamma^1, \gamma^2, \ldots, \gamma^B)^\top broadcast across the value dimensions.

The state update after processing chunk [i][i] is:

Ri=γBRi1+K[i](V[i]ζ)\boxed{R_i = \gamma^B \, R_{i-1} + K_{[i]}^\top (V_{[i]} \odot \zeta)}

where ζ\zeta is a matrix with row jj equal to (γBj,,γBj)(\gamma^{B-j}, \ldots, \gamma^{B-j}) — the decay from position jj within the chunk to the end of the chunk, broadcast across value dimensions. This ensures that the state RiR_i correctly accumulates contributions from all tokens up to and including chunk [i][i], with appropriate decay.

The complete chunkwise formula is:

Retention(X[i])=(Q[i]K[i]Dchunk)V[i]Inner-chunk+(Q[i]Ri1)ξCross-chunk\boxed{\text{Retention}(X_{[i]}) = \underbrace{(Q_{[i]} K_{[i]}^\top \odot D_\text{chunk}) V_{[i]}}_{\text{Inner-chunk}} + \underbrace{(Q_{[i]} R_{i-1}) \odot \xi}_{\text{Cross-chunk}}}

7.3 Numerical verification with B=2B = 2

Let us split our 4-token sequence into two chunks of B=2B = 2:

  • Chunk 1: tokens 1, 2
  • Chunk 2: tokens 3, 4

Chunk 1:

Q[1]=(1001),K[1]=(0110),V[1]=(1001)Q_{[1]} = \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix}, \quad K_{[1]} = \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix}, \quad V_{[1]} = \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix}

The chunk-level decay matrix (B=2B = 2):

Dchunk=(100.91)D_\text{chunk} = \begin{pmatrix} 1 & 0 \\ 0.9 & 1 \end{pmatrix}

Inner-chunk computation:

Q[1]K[1]=(1001)(0110)=(0110)Q_{[1]} K_{[1]}^\top = \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix} \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix} = \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix} Q[1]K[1]Dchunk=(0110)(100.91)=(000.90)Q_{[1]} K_{[1]}^\top \odot D_\text{chunk} = \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix} \odot \begin{pmatrix} 1 & 0 \\ 0.9 & 1 \end{pmatrix} = \begin{pmatrix} 0 & 0 \\ 0.9 & 0 \end{pmatrix} Inner1=(000.90)V[1]=(000.90)(1001)=(000.90)\text{Inner}_1 = \begin{pmatrix} 0 & 0 \\ 0.9 & 0 \end{pmatrix} V_{[1]} = \begin{pmatrix} 0 & 0 \\ 0.9 & 0 \end{pmatrix} \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix} = \begin{pmatrix} 0 & 0 \\ 0.9 & 0 \end{pmatrix}

Cross-chunk: R0=0R_0 = 0, so the cross-chunk contribution is zero.

Output chunk 1=(000.90)\text{Output chunk 1} = \begin{pmatrix} 0 & 0 \\ 0.9 & 0 \end{pmatrix} \quad \checkmark

State update for chunk 1:

ζ=(γB1γB1γB2γB2)=(0.90.911)\zeta = \begin{pmatrix} \gamma^{B-1} & \gamma^{B-1} \\ \gamma^{B-2} & \gamma^{B-2} \end{pmatrix} = \begin{pmatrix} 0.9 & 0.9 \\ 1 & 1 \end{pmatrix} V[1]ζ=(1001)(0.90.911)=(0.9001)V_{[1]} \odot \zeta = \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix} \odot \begin{pmatrix} 0.9 & 0.9 \\ 1 & 1 \end{pmatrix} = \begin{pmatrix} 0.9 & 0 \\ 0 & 1 \end{pmatrix} K[1](V[1]ζ)=(0110)(0.9001)=(010.90)K_{[1]}^\top (V_{[1]} \odot \zeta) = \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix} \begin{pmatrix} 0.9 & 0 \\ 0 & 1 \end{pmatrix} = \begin{pmatrix} 0 & 1 \\ 0.9 & 0 \end{pmatrix} R1=γBR0+K[1](V[1]ζ)=0+(010.90)=(010.90)R_1 = \gamma^B R_0 + K_{[1]}^\top (V_{[1]} \odot \zeta) = 0 + \begin{pmatrix} 0 & 1 \\ 0.9 & 0 \end{pmatrix} = \begin{pmatrix} 0 & 1 \\ 0.9 & 0 \end{pmatrix}

Verification: R1R_1 should equal S2S_2 from the recurrent computation (the state at the end of chunk 1). From Section 3.1: S2=(010.90)S_2 = \begin{pmatrix} 0 & 1 \\ 0.9 & 0 \end{pmatrix}. \checkmark

Chunk 2:

Q[2]=(1120),K[2]=(1102),V[2]=(1120)Q_{[2]} = \begin{pmatrix} 1 & 1 \\ 2 & 0 \end{pmatrix}, \quad K_{[2]} = \begin{pmatrix} 1 & 1 \\ 0 & 2 \end{pmatrix}, \quad V_{[2]} = \begin{pmatrix} 1 & 1 \\ 2 & 0 \end{pmatrix}

Inner-chunk:

Q[2]K[2]=(1120)(1012)=(2220)Q_{[2]} K_{[2]}^\top = \begin{pmatrix} 1 & 1 \\ 2 & 0 \end{pmatrix} \begin{pmatrix} 1 & 0 \\ 1 & 2 \end{pmatrix} = \begin{pmatrix} 2 & 2 \\ 2 & 0 \end{pmatrix} Q[2]K[2]Dchunk=(2220)(100.91)=(201.80)Q_{[2]} K_{[2]}^\top \odot D_\text{chunk} = \begin{pmatrix} 2 & 2 \\ 2 & 0 \end{pmatrix} \odot \begin{pmatrix} 1 & 0 \\ 0.9 & 1 \end{pmatrix} = \begin{pmatrix} 2 & 0 \\ 1.8 & 0 \end{pmatrix} Inner2=(201.80)V[2]=(201.80)(1120)=(221.81.8)\text{Inner}_2 = \begin{pmatrix} 2 & 0 \\ 1.8 & 0 \end{pmatrix} V_{[2]} = \begin{pmatrix} 2 & 0 \\ 1.8 & 0 \end{pmatrix} \begin{pmatrix} 1 & 1 \\ 2 & 0 \end{pmatrix} = \begin{pmatrix} 2 & 2 \\ 1.8 & 1.8 \end{pmatrix}

Cross-chunk:

Q[2]R1=(1120)(010.90)=(0.9102)Q_{[2]} R_1 = \begin{pmatrix} 1 & 1 \\ 2 & 0 \end{pmatrix} \begin{pmatrix} 0 & 1 \\ 0.9 & 0 \end{pmatrix} = \begin{pmatrix} 0.9 & 1 \\ 0 & 2 \end{pmatrix}

The decay vector ξ=(γ1,γ2)=(0.9,0.81)\xi = (\gamma^1, \gamma^2)^\top = (0.9, 0.81)^\top, broadcast across columns:

(Q[2]R1)ξ=(0.9102)(0.90.90.810.81)=(0.810.901.62)(Q_{[2]} R_1) \odot \xi = \begin{pmatrix} 0.9 & 1 \\ 0 & 2 \end{pmatrix} \odot \begin{pmatrix} 0.9 & 0.9 \\ 0.81 & 0.81 \end{pmatrix} = \begin{pmatrix} 0.81 & 0.9 \\ 0 & 1.62 \end{pmatrix}

Total output chunk 2:

Inner2+Cross2=(221.81.8)+(0.810.901.62)=(2.812.91.83.42)\text{Inner}_2 + \text{Cross}_2 = \begin{pmatrix} 2 & 2 \\ 1.8 & 1.8 \end{pmatrix} + \begin{pmatrix} 0.81 & 0.9 \\ 0 & 1.62 \end{pmatrix} = \begin{pmatrix} 2.81 & 2.9 \\ 1.8 & 3.42 \end{pmatrix} \quad \checkmark

Both tokens match the recurrent and parallel outputs.

State update for chunk 2:

ζ=(0.90.911)\zeta = \begin{pmatrix} 0.9 & 0.9 \\ 1 & 1 \end{pmatrix} V[2]ζ=(1120)(0.90.911)=(0.90.920)V_{[2]} \odot \zeta = \begin{pmatrix} 1 & 1 \\ 2 & 0 \end{pmatrix} \odot \begin{pmatrix} 0.9 & 0.9 \\ 1 & 1 \end{pmatrix} = \begin{pmatrix} 0.9 & 0.9 \\ 2 & 0 \end{pmatrix} K[2](V[2]ζ)=(1012)(0.90.920)=(0.90.94.90.9)K_{[2]}^\top (V_{[2]} \odot \zeta) = \begin{pmatrix} 1 & 0 \\ 1 & 2 \end{pmatrix} \begin{pmatrix} 0.9 & 0.9 \\ 2 & 0 \end{pmatrix} = \begin{pmatrix} 0.9 & 0.9 \\ 4.9 & 0.9 \end{pmatrix} R2=γBR1+K[2](V[2]ζ)=0.81(010.90)+(0.90.94.90.9)R_2 = \gamma^B R_1 + K_{[2]}^\top (V_{[2]} \odot \zeta) = 0.81 \begin{pmatrix} 0 & 1 \\ 0.9 & 0 \end{pmatrix} + \begin{pmatrix} 0.9 & 0.9 \\ 4.9 & 0.9 \end{pmatrix} =(00.810.7290)+(0.90.94.90.9)=(0.91.715.6290.9)= \begin{pmatrix} 0 & 0.81 \\ 0.729 & 0 \end{pmatrix} + \begin{pmatrix} 0.9 & 0.9 \\ 4.9 & 0.9 \end{pmatrix} = \begin{pmatrix} 0.9 & 1.71 \\ 5.629 & 0.9 \end{pmatrix}

Verification: R2R_2 should equal S4S_4 from the recurrent computation. From Section 3.1: S4=(0.91.715.6290.9)S_4 = \begin{pmatrix} 0.9 & 1.71 \\ 5.629 & 0.9 \end{pmatrix}. \checkmark

All three computation paradigms — recurrent, parallel, and chunkwise — produce identical outputs and identical final states. They are three views of the same mathematical object.

7.4 Chunkwise complexity

The cost of the chunkwise form per chunk:

  • Inner-chunk: Q[i]K[i]Q_{[i]} K_{[i]}^\top is (B×dk)×(dk×B)=O(B2dk)(B \times d_k) \times (d_k \times B) = O(B^2 d_k). Multiply by VV: O(B2dv)O(B^2 d_v). Total: O(B2dk)O(B^2 d_k).
  • Cross-chunk: Q[i]Ri1Q_{[i]} R_{i-1} is (B×dk)×(dk×dv)=O(Bdkdv)(B \times d_k) \times (d_k \times d_v) = O(B d_k d_v).
  • State update: K[i](V[i]ζ)K_{[i]}^\top (V_{[i]} \odot \zeta) is (dk×B)×(B×dv)=O(Bdkdv)(d_k \times B) \times (B \times d_v) = O(B d_k d_v).

There are n/Bn / B chunks. Total cost:

nB×(B2dk+Bdkdv)=nBdk+ndkdv=ndk(B+dv)\frac{n}{B} \times (B^2 d_k + B d_k d_v) = n B d_k + n d_k d_v = n d_k (B + d_v)

With B=512B = 512 and dk=dv=256d_k = d_v = 256 (RetNet’s experimental settings):

O(n256(512+256))=O(n256768)=O(n196,608)O(n \cdot 256 \cdot (512 + 256)) = O(n \cdot 256 \cdot 768) = O(n \cdot 196{,}608)

Compare to the parallel form: O(n2dk)=O(n2256)O(n^2 d_k) = O(n^2 \cdot 256). The chunkwise form becomes cheaper when B+dv<nB + d_v < n, which is 768<n768 < n — true for virtually all practical sequences.


8. Multi-Scale Retention

8.1 Different decay rates per head

A single decay rate γ\gamma pins the model to a single effective window. With γ=0.9\gamma = 0.9 we built a model that pays attention to the last ~44 tokens; with γ=0.99\gamma = 0.99 we would build one that reaches ~458 tokens but gives almost equal weight to everything in that window; with γ=0.5\gamma = 0.5 we would build one that effectively only sees the last ~7 tokens. Language has structure at all of these scales — a closing bracket binds to the most recent opening one (short window), a pronoun binds to its antecedent some sentences ago (medium), a topic word echoes across paragraphs (long). One γ\gamma cannot serve all three.

The fix is to make γ\gamma a per-head knob: assign each of the hh heads its own decay rate, spaced geometrically from “very forgetful” to “very persistent”. RetNet picks the spacing with the formula:

γ=125arange(0,h)Rh\boxed{\gamma = 1 - 2^{-5 - \text{arange}(0, h)} \in \mathbb{R}^h}

where arange(0,h)=(0,1,2,,h1)\text{arange}(0, h) = (0, 1, 2, \ldots, h-1) and the formula is applied element-wise, producing one γ\gamma per head. The 5-5 offset starts the smallest gap at 25=1/322^{-5} = 1/32 (so γ0=31/320.97\gamma_0 = 31/32 \approx 0.97, already a fairly long window), and each subsequent head halves the gap, pushing γ\gamma closer and closer to 1.

8.2 Numerical values for h=8h = 8 heads

Head ii5i-5 - i25i2^{-5-i}γi=125i\gamma_i = 1 - 2^{-5-i}Effective window (ϵ=0.01\epsilon = 0.01)
05-51/32=0.031251/32 = 0.031250.968750.96875145
16-61/64=0.0156251/64 = 0.0156250.9843750.984375292
27-71/1280.007811/128 \approx 0.007810.9921880.992188587
38-81/2560.003911/256 \approx 0.003910.9960940.9960941{,}177
49-91/5120.001951/512 \approx 0.001950.9980470.9980472{,}357
510-101/10240.0009771/1024 \approx 0.0009770.9990230.9990234{,}717
611-111/20480.0004881/2048 \approx 0.0004880.9995120.9995129{,}439
712-121/40960.0002441/4096 \approx 0.0002440.9997560.99975618{,}882

The effective window is computed as d=log(0.01)/log(γi)d = \log(0.01) / \log(\gamma_i), the formula from Section 2.3.

Head 0 has γ=0.969\gamma = 0.969 with an effective window of ~145 tokens — it focuses on local patterns. Head 7 has γ=0.9998\gamma = 0.9998 with an effective window of ~18,882 tokens — it captures long-range dependencies. This is multi-scale retention (MSR): the heads automatically specialize at different scales, similar to how multi-resolution wavelets capture patterns at different frequencies.

8.3 Why multiple scales help

The ablation in Table 6 of Sun et al. (2023) quantifies the contribution:

VariantIn-Domain PPL
RetNet (full)26.05
- γ\gamma decay (set γ=1\gamma = 1)27.86
- multi-scale decay (same γ\gamma for all heads)27.02

Removing decay entirely (γ=1\gamma = 1) degrades perplexity by 1.81 — this reverts retention to linear attention, confirming that decay is essential. Using a single decay rate across all heads degrades perplexity by 0.97 — confirming that multi-scale specialization provides meaningful improvement beyond the decay mechanism itself.

8.4 GroupNorm instead of LayerNorm

Since different heads use different γ\gamma values, their output magnitudes differ. A head with γ=0.969\gamma = 0.969 accumulates less state (more decay) and produces smaller outputs than a head with γ=0.9998\gamma = 0.9998 (less decay). Applying LayerNorm across all heads would couple their normalization statistics, distorting the relative scales.

RetNet uses GroupNorm (Wu and He, 2018) instead, which normalizes each head independently. Formally, if headiRn×dv\text{head}_i \in \mathbb{R}^{n \times d_v} is the output of the ii-th retention head:

Y=GroupNormh(Concat(head1,,headh))Y = \text{GroupNorm}_h(\text{Concat}(\text{head}_1, \ldots, \text{head}_h))

where the GroupNorm has hh groups, one per head. Each head is normalized by its own mean and variance, preserving the different scales induced by different γ\gamma values.

The ablation confirms this: removing GroupNorm degrades perplexity from 26.05 to 27.54 (a 1.49 increase).

An important property of GroupNorm is scale invariance: GroupNorm(αheadi)=GroupNorm(headi)\text{GroupNorm}(\alpha \cdot \text{head}_i) = \text{GroupNorm}(\text{head}_i) for any scalar α>0\alpha > 0. This means the retention outputs do not need to be normalized by a denominator (unlike linear attention’s ϕ(qi)zi\phi(q_i)^\top z_i normalization). The GroupNorm absorbs any global scaling. This is why retention can use raw query-key products — even if the products are large or negative, the GroupNorm handles the scale.

8.5 Retention Score Normalization

The scale invariance of GroupNorm also enables additional normalization tricks that improve numerical precision without changing the final output. Sun et al. (2023) apply three normalization factors:

  1. Scale QKQK^\top by 1/d1/\sqrt{d} (same as the 1/dk1/\sqrt{d_k} scaling in standard attention).
  2. Normalize the decay matrix: replace DnmD_{nm} with D~nm=Dnm/i=1nDni\tilde{D}_{nm} = D_{nm} / \sqrt{\sum_{i=1}^n D_{ni}}.
  3. Normalize the retention scores: R~nm=Rnm/max(i=1nRni,1)\tilde{R}_{nm} = R_{nm} / \max(|\sum_{i=1}^n R_{ni}|, 1).

These tricks stabilize the numerical flow in both forward and backward passes. Because of GroupNorm’s scale invariance, they do not affect the final output or gradients — they only improve intermediate precision.


9. The Complete RetNet Block

9.1 The MSR layer

The multi-scale retention (MSR) module combines the retention heads with a swish gate:

headi=Retention(X,γi)\text{head}_i = \text{Retention}(X, \gamma_i) Y=GroupNormh(Concat(head1,,headh))Y = \text{GroupNorm}_h(\text{Concat}(\text{head}_1, \ldots, \text{head}_h)) MSR(X)=(swish(XWG)Y)WO\boxed{\text{MSR}(X) = (\text{swish}(X W_G) \odot Y) \, W_O}

where WGRdmodel×dmodelW_G \in \mathbb{R}^{d_\text{model} \times d_\text{model}} and WORdmodel×dmodelW_O \in \mathbb{R}^{d_\text{model} \times d_\text{model}} are learned parameter matrices. The swish activation (Ramachandran et al., 2017) is swish(x)=xσ(x)\text{swish}(x) = x \cdot \sigma(x) where σ\sigma is the sigmoid function.

The swish gate swish(XWG)Y\text{swish}(X W_G) \odot Y is a multiplicative interaction between the raw input (passed through a linear layer and swish) and the retention output. This is the same gating principle we derived in the Gated Attention blog — learned, per-dimension multiplicative control of information flow. The gate increases the non-linearity of the retention layer, which is important because the retention mechanism itself (without softmax) is a linear function of the values.

The ablation from Sun et al. (2023) confirms: removing the swish gate degrades perplexity from 26.05 to 27.84 (a 1.79 increase). This is the largest single-component degradation in the ablation, even larger than removing decay (+1.81+1.81) — indicating that the gate is essential for model quality.

9.2 The full RetNet block

Each RetNet layer consists of an MSR module and a feed-forward network (FFN), with pre-norm residual connections (the same layout we derived in the Gated Attention blog, Section 2.2):

Yl=MSR(LN(Xl))+XlY^l = \text{MSR}(\text{LN}(X^l)) + X^l Xl+1=FFN(LN(Yl))+YlX^{l+1} = \text{FFN}(\text{LN}(Y^l)) + Y^l

where LN\text{LN} is LayerNorm (Ba et al., 2016). The FFN uses GELU activation:

FFN(X)=gelu(XW1)W2\text{FFN}(X) = \text{gelu}(X W_1) W_2

with W1Rdmodel×dffW_1 \in \mathbb{R}^{d_\text{model} \times d_{ff}} and W2Rdff×dmodelW_2 \in \mathbb{R}^{d_{ff} \times d_\text{model}}.

9.3 Parameter allocation

RetNet re-allocates parameters between the MSR and FFN modules to match the total parameter count of a standard transformer.

In a transformer: self-attention has 4d24d^2 parameters (WQ,WK,WV,WOW_Q, W_K, W_V, W_O, each d×dd \times d), and FFN has 8d28d^2 parameters (W1Rd×4dW_1 \in \mathbb{R}^{d \times 4d}, W2R4d×dW_2 \in \mathbb{R}^{4d \times d}). Total: 12d212d^2.

In RetNet: MSR has WQ,WKRd×dW_Q, W_K \in \mathbb{R}^{d \times d}, WVRd×2dW_V \in \mathbb{R}^{d \times 2d} (the value head dimension is twice the query/key dimension), WGRd×dW_G \in \mathbb{R}^{d \times d}, and WOR2d×dW_O \in \mathbb{R}^{2d \times d} (projecting from the widened value dimension back to dd). That is d2+d2+2d2+d2+2d2=8d2d^2 + d^2 + 2d^2 + d^2 + 2d^2 = 8d^2.

To keep the total at 12d212d^2, the FFN intermediate dimension is reduced to 2d2d (from 4d4d), giving 4d24d^2 for FFN. Total: 8d2+4d2=12d28d^2 + 4d^2 = 12d^2.

9.4 Numerical check

With dmodel=512d_\text{model} = 512:

  • Transformer: 12×5122=3,145,72812 \times 512^2 = 3{,}145{,}728 parameters per layer
  • RetNet: 12×5122=3,145,72812 \times 512^2 = 3{,}145{,}728 parameters per layer \checkmark

The parameter counts match exactly. Any difference in performance comes from the architecture, not from having more or fewer parameters.


10. Experimental Results

Sun et al. (2023) evaluate RetNet against Transformers and other efficient architectures across multiple dimensions.

10.1 Language modeling

RetNet and Transformer are trained from scratch at three scales (1.3B, 2.7B, 6.7B parameters) on 100B tokens from The Pile, C4, and The Stack. The validation perplexities:

Model SizeTransformer PPLRetNet PPL
1.3B~15.0~14.8
2.7B~13.5~13.3
6.7B~12.8~12.5

RetNet achieves comparable or better perplexity at every scale. The gap widens in RetNet’s favor as models get larger — a favorable scaling trend.

10.2 Zero-shot and few-shot evaluation

On seven downstream tasks (HellaSwag, BoolQ, COPA, PIQA, Winograd, Winogrande, StoryCloze) with the 6.7B model:

SettingTransformer AvgRetNet Avg
Zero-shot66.0769.51
4-shot66.4469.76

RetNet outperforms the Transformer on average in both zero-shot and few-shot settings. The improvements are consistent across individual tasks.

10.3 Training cost

Training throughput and memory on 8 NVIDIA A100-80GB GPUs with sequence length 8192:

Model SizeTrm Memory (GB)RetNet Memory (GB)Trm Throughput (wps)RetNet Throughput (wps)
1.3B74.834.510{,}83273{,}345
2.7B69.642.05{,}18638{,}921
6.7B69.048.02{,}75417{,}459
13B61.445.91{,}2098{,}642

RetNet uses 25–54% less memory and achieves 6–7×\times higher throughput than vanilla Transformer. Even compared to FlashAttention-optimized Transformers, RetNet is competitive — and RetNet’s implementation uses vanilla PyTorch without custom kernels.

10.4 Inference cost

At 6.7B scale with 8K sequence length, the recurrent form gives:

  • Memory: 3.4×\times less GPU memory (RetNet’s state is constant, Transformer’s KV cache grows)
  • Throughput: 8.4×\times higher (words per second)
  • Latency: 15.6×\times lower (milliseconds per token)

RetNet’s inference latency is batch-size invariant — it stays nearly constant whether processing 1 or 8 sequences simultaneously. Transformer latency grows with batch size because the KV cache competes for GPU memory with the computation.

10.5 Comparison with other efficient architectures

At 200M parameters with 16 layers and hidden dimension 1024:

MethodIn-Domain PPLPG22QMSumGovReportSummScreen
RWKV30.9251.4128.1719.8025.78
H329.9749.1724.2919.1925.11
Hyena32.0852.7528.1820.5526.51
Linear Transformer40.2463.8628.4525.3332.02
RetNet26.0545.2721.3316.5222.48

RetNet outperforms all other efficient architectures on both in-domain and out-of-domain corpora. The Linear Transformer (the Why Replace Attention blog’s architecture) is the weakest — confirming that replacing softmax with a simple kernel without decay or position encoding loses too much modeling capacity.

10.6 Context length results

RetNet maintains its advantage across different context lengths:

Model51210242048
Transformer13.5512.5612.35
RetNet13.0912.1411.98

RetNet consistently achieves lower perplexity, and the gap slightly widens with longer contexts. The exponential decay does not prevent the model from using long-range context — the heads with γ0.9998\gamma \approx 0.9998 have effective windows of nearly 19,000 tokens, covering most practical sequence lengths.


11. The Hybrid Architecture Pattern

11.1 What makes an architecture hybrid

We can now define precisely what a hybrid architecture means in this context. A hybrid sequence model satisfies three properties:

  1. A single mathematical formula defines the input-output mapping. There is one function, not two.
  2. Multiple computation modes implement this formula. Each mode has different cost characteristics (parallel vs sequential, quadratic vs linear memory) suited to different hardware contexts.
  3. Exact equivalence between modes. The outputs are identical — not approximated, not distilled, not fine-tuned separately. The same trained weights produce the same outputs regardless of which mode is used.

RetNet’s retention satisfies all three:

Parallel (training): Retention(X)=(QKD)V\text{Retention}(X) = (QK^\top \odot D) V. Cost: O(n2dk)O(n^2 d_k). GPU-efficient matrix operations. Used when the full sequence is available.

Recurrent (inference): Sn=γSn1+knvnS_n = \gamma S_{n-1} + k_n v_n^\top, on=qnSno_n = q_n^\top S_n. Cost: O(dk2)O(d_k^2) per token. Constant memory, constant compute. Used for autoregressive generation.

Chunkwise (long-sequence training): parallel within chunks of size BB, recurrent across chunks. Cost: O(ndk(B+dk))O(n d_k (B + d_k)). Balances parallelism and memory. Used when sequences are too long for the full parallel form.

We verified numerically that all three produce identical outputs for every token. The equivalence is a mathematical property of the retention formula itself, not an engineering trick.

11.2 Why the hybrid pattern is general

The retention mechanism is not the only formula with this property. The mathematical ingredients that enable the hybrid pattern are:

  1. A linear recurrence with state Sn=ASn1+BnS_n = A S_{n-1} + B_n. Any linear recurrence can be unrolled into a sum (yielding a parallel form) or executed step by step (yielding a recurrent form).
  2. Associativity of matrix multiplication. The parallel form is just a different parenthesization of the same matrix product — (QK)V(QK^\top)V vs Q(KV)Q(K^\top V).
  3. Decomposability into chunks. The sum in the unrolled form can be split at any chunk boundary, giving the chunkwise form.

Any mechanism built on a linear recurrence inherits this hybrid property. This is why the pattern appears repeatedly in the architectures that followed RetNet: Mamba (Gu and Dao, 2023), RWKV (Peng et al., 2023), Griffin (De et al., 2024), and others all have parallel training and recurrent inference modes derived from the same linear recurrence structure. The specific choices — what goes into the state, how the state decays, how position is encoded — differ across architectures, but the hybrid pattern is the same.

11.3 From the Why Replace Attention blog to RetNet

The Why Replace Attention blog showed that linear attention is an RNN:

Snlinear=Sn1linear+ϕ(kn)vnS_n^{\text{linear}} = S_{n-1}^{\text{linear}} + \phi(k_n) v_n^\top

This was the first hybrid architecture: it had a parallel form and a recurrent form. But it failed at the third vertex of the impossible triangle — strong performance — because the accumulate-only recurrence lost information and lacked position encoding.

RetNet’s retention is a direct modification of this recurrence:

Snretention=γSn1retention+knvnS_n^{\text{retention}} = \gamma S_{n-1}^{\text{retention}} + k_n v_n^\top

The two changes — adding γ\gamma and dropping the kernel feature map ϕ\phi — are small algebraically but large in effect. The decay factor γ\gamma bounds the state, encodes recency, and (through multi-scale heads) creates a rich set of temporal attention windows. Dropping the kernel and replacing the denominator normalization with GroupNorm gives the model more flexibility — the query-key interaction can be negative, and the normalization is data-adaptive rather than formula-fixed.

The position encoding via complex exponentials (einθe^{i n \theta}) arises naturally from diagonalizing the state transition matrix — it is not an add-on but a structural consequence of the recurrence.

RetNet is the first architecture to convincingly demonstrate that the hybrid pattern can achieve all three vertices of the impossible triangle. It established the template — linear recurrence + exponential decay + multi-scale heads + gating — that subsequent architectures have refined and extended.


Summary

The Why Replace Attention blog’s linear attention was the first hybrid architecture: one formula with both a parallel form and a recurrent form. But it failed at quality because the accumulate-only recurrence (Sn=Sn1+ϕ(kn)vnS_n = S_{n-1} + \phi(k_n)v_n^\top) grows without bound and has no position information. RetNet fixes both problems by adding exponential decay γ\gamma (bounding the state at c/(1γ)c/(1-\gamma) via the geometric series limit) and relative position encoding via complex exponentials (ei(nm)θe^{i(n-m)\theta}, derived from diagonalizing the state transition matrix AA). The result is a hybrid architecture with three equivalent computation paradigms — parallel for training ((QKD)V(QK^\top \odot D)V, cost O(n2dk)O(n^2 d_k)), recurrent for inference (O(dk2)O(d_k^2) per token, constant memory), and chunkwise for long sequences (O(ndk(B+dk))O(n d_k(B + d_k))) — all verified to produce identical outputs on a 4-token running example. Multi-scale retention assigns different decay rates per head (γ\gamma from 0.9690.969 to 0.99980.9998 for 8 heads), giving effective attention windows from 145 to 18,882 tokens, and the swish gate plus GroupNorm complete the architecture to match transformer parameter counts while achieving 8.4×\times faster inference, 15.6×\times lower latency, and competitive-or-better perplexity. This is the hybrid architecture pattern: one formula, multiple computation modes, exact equivalence — the template that Mamba, RWKV, Griffin, and other post-transformer architectures all follow.


Previous: Why Replace Attention? The Softmax Bottleneck and the Path to Linear Time

Next: Targeted Memory: The Delta Rule, Gated DeltaNet, and Kimi Delta Attention

Enjoyed this post?

Subscribe to get notified when I publish new posts. No spam, unsubscribe anytime.