The whole block

Put the pieces together: LayerNorm, attention, add; LayerNorm, MLP, add. That is one transformer block, and a model is a stack of identical blocks between an embedding table and an output layer. Here is one block computed number by number, and an exact parameter count for real models.

Key idea
x ← x + Attn(LN(x)); x ← x + MLP(LN(x)); stack N times; count parameters ≈ 12·N·d² + vocab·d
Real world
An assembly line of identical workstations. Each station has the same two tools, a “look around” tool and a “think about it” tool, and adds its work to the product on the belt. A bigger factory just has more stations and wider belts.
In an LLM
GPT-2 small is 12 identical blocks with width 768: 124 million parameters. Llama 3 70B is 80 blocks with width 8,192: 70.6 billion. Same recipe, different sizes.

One block, start to finish

You have met every part. A pre-norm , as used by GPT-2 and Llama, is:

x′=x+Attention⁡(LN⁡1(x))xout=x′+MLP⁡(LN⁡2(x′))\begin{aligned} x' &= x + \operatorname{Attention}\big(\operatorname{LN}_1(x)\big)\\ x_{\text{out}} &= x' + \operatorname{MLP}\big(\operatorname{LN}_2(x')\big) \end{aligned}

where xx is the whole sequence, one row per token. Six steps:

  1. LayerNorm each token’s row (a copy; xx itself is kept). Normalization.
  2. Attention on the normalised copy: queries, keys, values, scores, mask, softmax, mix, then an output matrix WOW_O that maps the heads’ results back to the model width. Queries, keys and values, multi-head.
  3. Add the attention output to xx. The residual stream.
  4. LayerNorm again.
  5. MLP on each token separately: widen, activate, narrow. The MLP.
  6. Add the MLP output.

The shape on the main path never changes: TT tokens × dd numbers in, T×dT \times d out. That is what lets blocks stack.

input
→→→→→→
follow:
x5 × 4
thingact.smallfirstThe0.10.01.01.0cat1.00.10.00.0sat0.21.00.00.0on0.00.30.80.0the0.10.01.00.0
−2.02.0
The block’s input: 5 tokens × 4 numbers. Click a token to follow its row. Every step below keeps the shape 5 × 4 on the main path.
One complete pre-norm transformer block on the toy sentence. Every number is computed live: the attention weights come from the toy head, the MLP weights from the MLP page. Press play or click a stage.

The toy uses width 4 so you can read every number. GPT-2 small does the same with width 768, 12 heads of size 64 and an MLP of width 3072, in each of its 12 blocks.

The whole model

A full decoder-only transformer is:

  1. Embed: look up each token’s row in the embedding table, add position information. Embeddings, positions.
  2. Blocks: run the T×dT \times d matrix through NN identical blocks (each with its own weights).
  3. Final norm and unembed: normalise, multiply by the output matrix to get one score per vocabulary token. Unembedding.
ModelBlocks NNWidth ddHeadsMLP widthVocabulary
GPT-2 small12768123,07250,257
GPT-2 XL481,600256,40050,257
Llama 3 8B324,09632 (8 KV)14,336128,256
Llama 3 70B808,19264 (8 KV)28,672128,256

Counting the parameters

Every parameter lives in one of five places: the embedding table, the attention matrices, the MLP matrices, the norms, and (unless it is tied to the embedding) the output matrix. With full multi-head attention and a 4× MLP, each block has about 4d2+8d2=12d24d^2 + 8d^2 = 12d^2 weights, so

parameters≈12 N d2+vocab×d.\text{parameters} \approx 12\,N\,d^2 + \text{vocab} \times d.

For GPT-2 small: 12×12×7682=84.9M12 \times 12 \times 768^2 = 84.9\text{M} in the blocks plus 50,257×768=38.6M50{,}257 \times 768 = 38.6\text{M} in the embeddings, 123.5M; the biases, norms and position table bring it to exactly 124,439,808. Try the presets:

32%23%46%
embeddings 39.4Mattention 28.3MMLPs 56.7Mnorms 38.4K
where the formula comes from
embeddings = vocab × d + positions (1024) × dattention / layer = 2d² (Q, O) + 2 × d × kv·d/heads (K, V) + biasesMLP / layer = 2 × d × d_ff + biasesnorms = 2 per layer × 2d (gain, bias) + a final oneoutput layer = 0 (shares the embedding matrix)
total parameters124,439,808
per block7.1M
in bf16 (2 bytes each)249 MB
GPT-2 small: 124,439,808 parameters, exactly the 124,439,808 in the published checkpoint (Hugging Face gpt2). The MLPs are 46% of it.
Every weight matrix and vector in the model, counted from the configuration. Pick a preset (the total is checked against the published checkpoint) or move the sliders to design your own.

Every preset matches the published checkpoint to the last parameter. Two things to notice:

  • Blocks grow with d2d^2, embeddings with dd. In GPT-2 small the token and position tables are 32% of the model; in Llama 3 70B the embedding and output matrices together are only 3%. Small models spend a surprising share on their vocabulary.
  • Bytes follow directly. Stored in bf16 (2 bytes per parameter) Llama 3 8B needs about 16 GB just for its weights, before the KV cache and activations. How much memory a model needs works through this, and how quantization shrinks it.
example · an assembly line

A car factory has a line of identical workstations. At each one, a worker looks at the car and at the cars next to it on the line (attention), thinks about what this car needs (the MLP), and bolts on a part (the add). Nothing is ever removed. A bigger factory doesn’t invent new kinds of station; it builds more of them and makes the line wider. Doubling the width of every station roughly quadruples the cost of each one, which is the d2d^2.

example · GPT-2 small to Llama 3 70B

GPT-2 small (2019) and Llama 3 70B (2024) are built from the same block. Llama swaps LayerNorm for RMSNorm, GELU for SwiGLU, learned positions for RoPE, and shares keys and values across groups of heads. It is 6.7 times deeper and 10.7 times wider, and 10.7² × 6.7 ≈ 760: almost all of the 567-fold growth in parameters (124M to 70.6B) comes from width squared times depth.

What one block costs to run

Each parameter in a block is used once per token in one multiply and one add, so a forward pass costs about 2×parameters2 \times \text{parameters} floating-point operations per token, plus the attention scores that grow with the context length. What a forward pass costs works this out properly.

going deeper

The complete count

With hh query heads, hkvh_{kv} key–value heads, head size dh=d/hd_h = d/h, MLP width dffd_{ff} and vocabulary VV:

attention=2d2+2 d hkvdh  (+biases)MLP=2 d dff  (GELU, + biases)or3 d dff  (SwiGLU)norms=2 per block×d  (RMSNorm) or 2d  (LayerNorm)total=Vd  (+Pd learned positions)+N(attention+MLP+norms)+final norm  (+Vd if untied)\begin{aligned} \text{attention} &= 2d^2 + 2\,d\,h_{kv} d_h \;(+\text{biases})\\ \text{MLP} &= 2\,d\,d_{ff} \;(\text{GELU, + biases}) \quad\text{or}\quad 3\,d\,d_{ff} \;(\text{SwiGLU})\\ \text{norms} &= 2 \text{ per block} \times d \;(\text{RMSNorm}) \text{ or } 2d \;(\text{LayerNorm})\\ \text{total} &= V d \;(+ P d \text{ learned positions}) + N(\text{attention} + \text{MLP} + \text{norms}) + \text{final norm} \;(+ V d \text{ if untied}) \end{aligned}

Check it yourself

from transformers import AutoModelForCausalLM
m = AutoModelForCausalLM.from_pretrained("gpt2")
print(sum(p.numel() for p in m.parameters()))   # 124439808 (the tied output matrix is counted once)

In papers

Related

  • residual-stream - Every token carries one vector up through the model. Each attention layer and each MLP reads that vector, computes something, and adds the result back. Nothing is overwritten. This running sum is the residual stream, and it is why deep transformers can be trained at all.
  • normalization - Before each attention layer and each MLP, the model rescales the token’s vector to a standard size. LayerNorm subtracts the mean and divides by the standard deviation; RMSNorm just divides by the root mean square. Where the norm sits, before the layer or after it, decides whether a deep model trains.
  • mlp - After attention has moved information between tokens, the MLP processes each token on its own: widen the vector four times, bend it with an activation function, narrow it back. Its neurons act like key–value memories, and it holds most of the model’s parameters.
  • unembedding - At the top of the stack, the last token’s vector is normalised and multiplied by one big matrix that gives a score to every token in the vocabulary. Softmax turns the scores into probabilities. Applying the same read-out to the middle layers, the logit lens, shows the prediction taking shape.
  • cost - A transformer does about 2 FLOPs per parameter for every token it reads, 6 when training, plus an attention term that grows with the context. But when generating for one user, arithmetic is not the bottleneck. Every new token has to read every weight from memory, so speed is set by memory bandwidth, and batching many users together is almost free.