Navigation
πŸ“ FoundationsΒ· 18 min read

The Transformer as a Compute Graph

Trace the complete forward pass of a decoder-only Transformer β€” tensor shapes, FLOP counts, and parameter counting at every step.

transformerdecoder-onlyforward-passparameter-countingshapes

Every optimization in AI infrastructure β€” kernel design, parallelism strategy, memory management β€” acts on some component of the Transformer. This chapter traces the complete forward pass of a decoder-only Transformer, tracking tensor shapes, data dependencies, and compute costs at every step. The goal: see the Transformer not as an abstract diagram but as a concrete sequence of matrix operations with measurable costs.


1. The Decoder-Only Architecture

Modern LLMs (GPT, LLaMA, Qwen, Mistral, DeepSeek) all use the decoder-only architecture. The full pipeline:

Input tokens β†’ Embedding β†’ N Γ— Decoder Block β†’ Final Norm β†’ LM Head β†’ Logits

End-to-End Data Flow

Tracing a single forward pass with concrete shapes:

Input: "What is attention" β†’ Tokenizer β†’ [1234, 567, 89]  (S=3 tokens)

Step 1: Token Embedding
  token_ids (B, S)  β†’  W_embed (V, d)  β†’  X (B, S, d)
  (1, 3)                (32000, 4096)      (1, 3, 4096)

Step 2: L Γ— Decoder Block (shape preserved throughout)
  β”Œβ”€ Block ──────────────────────────────────────────────┐
  β”‚  x_norm = RMSNorm(X)                    (B, S, d)   β”‚
  β”‚  attn_out = MaskedSelfAttention(x_norm) (B, S, d)   β”‚
  β”‚  H = X + attn_out                ← residual         β”‚
  β”‚                                                      β”‚
  β”‚  h_norm = RMSNorm(H)                    (B, S, d)   β”‚
  β”‚  ffn_out = SwiGLU_FFN(h_norm)           (B, S, d)   β”‚
  β”‚  X_out = H + ffn_out             ← residual         β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       Γ— L layers (dimension stays (B, S, d) throughout)

Step 3: Final RMSNorm
  X_final (B, S, d)  β†’  RMSNorm  β†’  X_norm (B, S, d)

Step 4: LM Head
  X_norm (B, S, d)  Γ—  W_lm (d, V)  =  logits (B, S, V)
  (1, 3, 4096)         (4096, 32000)    (1, 3, 32000)

Step 5: Take last position, softmax β†’ sample next token
  logits[:, -1, :]  β†’  softmax  β†’  sample  β†’  next token

Key observation: the hidden dimension dd is preserved through all L blocks. The only shape changes happen at input (token IDs β†’ embeddings) and output (embeddings β†’ vocabulary logits).


2. Inside a Decoder Block

Each decoder block has two sub-layers: masked self-attention and feed-forward network, each wrapped with normalization and residual connections.

Decoder Block

Masked Self-Attention

Attention(Q,K,V)=softmax(QK⊀dk+M)V\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^\top}{\sqrt{d_k}} + M\right)V

Where MM is the causal mask β€” an upper-triangular matrix of βˆ’βˆž-\infty that prevents attending to future tokens.

Step by step with shapes (for a single head):

StepOperationShape
InputX\mathbf{X}(B,S,d)(B, S, d)
Q projectionQ=XWQ\mathbf{Q} = \mathbf{X}\mathbf{W}_Q(B,S,d)Γ—(d,d)β†’(B,S,d)(B, S, d) \times (d, d) \to (B, S, d)
K projectionK=XWK\mathbf{K} = \mathbf{X}\mathbf{W}_K(B,S,d)Γ—(d,d)β†’(B,S,d)(B, S, d) \times (d, d) \to (B, S, d)
V projectionV=XWV\mathbf{V} = \mathbf{X}\mathbf{W}_V(B,S,d)Γ—(d,d)β†’(B,S,d)(B, S, d) \times (d, d) \to (B, S, d)
Split headsReshape + transpose(B,Nh,S,dk)(B, N_h, S, d_k) where dk=d/Nhd_k = d / N_h
Attention scoresQK⊀/dk\mathbf{Q}\mathbf{K}^\top / \sqrt{d_k}(B,Nh,S,dk)Γ—(B,Nh,dk,S)β†’(B,Nh,S,S)(B, N_h, S, d_k) \times (B, N_h, d_k, S) \to (B, N_h, S, S)
Causal maskAdd βˆ’βˆž-\infty to upper triangle(B,Nh,S,S)(B, N_h, S, S)
SoftmaxRow-wise softmax(B,Nh,S,S)(B, N_h, S, S)
Weighted sumAttnΓ—V\text{Attn} \times \mathbf{V}(B,Nh,S,S)Γ—(B,Nh,S,dk)β†’(B,Nh,S,dk)(B, N_h, S, S) \times (B, N_h, S, d_k) \to (B, N_h, S, d_k)
Merge headsReshape(B,S,d)(B, S, d)
Output projectionWO\mathbf{W}_O(B,S,d)Γ—(d,d)β†’(B,S,d)(B, S, d) \times (d, d) \to (B, S, d)

The SΓ—SS \times S attention matrix is why attention is O(S2)O(S^2) in memory and compute β€” and why long-context serving is hard.

Feed-Forward Network (SwiGLU)

Modern LLMs use SwiGLU instead of the original ReLU FFN:

FFN(x)=(Swish(xWgate)βŠ™xWup)Wdown\text{FFN}(\mathbf{x}) = (\text{Swish}(\mathbf{x}\mathbf{W}_{\text{gate}}) \odot \mathbf{x}\mathbf{W}_{\text{up}}) \mathbf{W}_{\text{down}}
StepOperationShape
Gate projectionxWgate\mathbf{x}\mathbf{W}_{\text{gate}}(B,S,d)Γ—(d,dff)β†’(B,S,dff)(B, S, d) \times (d, d_{ff}) \to (B, S, d_{ff})
Up projectionxWup\mathbf{x}\mathbf{W}_{\text{up}}(B,S,d)Γ—(d,dff)β†’(B,S,dff)(B, S, d) \times (d, d_{ff}) \to (B, S, d_{ff})
Gate activationSwish(gate)βŠ™up\text{Swish}(\text{gate}) \odot \text{up}(B,S,dff)(B, S, d_{ff})
Down projectionWdown\mathbf{W}_{\text{down}}(B,S,dff)Γ—(dff,d)β†’(B,S,d)(B, S, d_{ff}) \times (d_{ff}, d) \to (B, S, d)

SwiGLU has 3 weight matrices (gate, up, down) instead of 2 β€” this changes parameter counting.

RMSNorm

RMSNorm(x)=Ξ³βŠ™x1dβˆ‘i=1dxi2+Ο΅\text{RMSNorm}(\mathbf{x}) = \gamma \odot \frac{\mathbf{x}}{\sqrt{\frac{1}{d}\sum_{i=1}^{d} x_i^2 + \epsilon}}

Only dd learnable parameters (the scale Ξ³\gamma). Compared to LayerNorm, RMSNorm skips mean centering β€” ~10-15% faster with comparable quality. Used by LLaMA, Qwen, Mistral, and most modern LLMs.


3. Model Configurations

Different model sizes use the same decoder block β€” just with different dimensions:

ModelddNhN_hNkvN_{kv}dkd_kLLdffd_{ff}VVAttention
LLaMA-2-7B409632321283211,00832,000MHA
LLaMA-2-13B512040401284013,82432,000MHA
LLaMA-2-70B81926481288028,67232,000GQA
Mistral-7B40963281283214,33632,000GQA
DeepSeek-V37168128β€”β€”6118,432129,280MLA + MoE

Patterns to notice:

  • dk=128d_k = 128 is universal: every model uses 128-dim attention heads. Scaling up means more heads, not bigger heads.
  • SwiGLU changes dffd_{ff}: standard Transformer uses dff=4dd_{ff} = 4d. SwiGLU has 3 matrices instead of 2, so dffβ‰ˆ(8/3)dd_{ff} \approx (8/3)d to keep parameter count similar. LLaMA-2-7B: (8/3)Γ—4096=10,923β†’11,008(8/3) \times 4096 = 10,923 \to 11,008 (rounded to 256 for GPU alignment).
  • GQA reduces KV heads: LLaMA-2-70B uses 8 KV heads for 64 Q heads β€” each group of 8 Q heads shares 1 KV head. This cuts KV cache by 8Γ— with minimal quality loss.

4. Parameter Counting

Estimating parameters is a fundamental AI infra skill β€” it directly tells you memory requirements.

Per-Block Parameters

For a single decoder block with MHA and SwiGLU:

ComponentFormulaCount (7B, d=4096d=4096)
Q projection WQ\mathbf{W}_QdΓ—dd \times d16.8M
K projection WK\mathbf{W}_KdΓ—dd \times d16.8M
V projection WV\mathbf{W}_VdΓ—dd \times d16.8M
O projection WO\mathbf{W}_OdΓ—dd \times d16.8M
Gate Wgate\mathbf{W}_{\text{gate}}dΓ—dffd \times d_{ff}45.1M
Up Wup\mathbf{W}_{\text{up}}dΓ—dffd \times d_{ff}45.1M
Down Wdown\mathbf{W}_{\text{down}}dffΓ—dd_{ff} \times d45.1M
2Γ— RMSNorm2d2d8.2K
Block total4d2+3dβ‹…dff+2d4d^2 + 3d \cdot d_{ff} + 2d202M

Total Model Parameters

ComponentFormulaCount (LLaMA-2-7B)
EmbeddingVΓ—dV \times d131M
LL blocksLΓ—PblockL \times P_{\text{block}}32 Γ— 202M = 6,464M
Final RMSNormdd4K
LM HeaddΓ—Vd \times V131M (often tied with embedding)
Total~6.7B

With GQA (LLaMA-2-70B)

When Nkv<NhN_{kv} < N_h, K and V projections shrink:

Pattn=dβ‹…(Nhβ‹…dk)+2β‹…dβ‹…(Nkvβ‹…dk)+(Nhβ‹…dk)β‹…dP_{\text{attn}} = d \cdot (N_h \cdot d_k) + 2 \cdot d \cdot (N_{kv} \cdot d_k) + (N_h \cdot d_k) \cdot d

For 70B: Nh=64,Nkv=8,dk=128,d=8192N_h=64, N_{kv}=8, d_k=128, d=8192:

  • Q and O: 2Γ—8192Γ—8192=134M2 \times 8192 \times 8192 = 134M
  • K and V: 2Γ—8192Γ—1024=16.8M2 \times 8192 \times 1024 = 16.8M
  • Attention per block: 150.8M (vs 268M with full MHA β€” 44% reduction)

5. FLOP Counting

For a forward pass with batch size BB, sequence length SS, and model parameters:

Per-token compute (single decoder block):

OperationFLOPs
QKV + O projections8BSd28BSd^2
Attention scores QK⊀QK^\top2BNhS2dk2BN_hS^2d_k
Attention Γ— V2BNhS2dk2BN_hS^2d_k
FFN (SwiGLU, 3 matrices)6BSdβ‹…dff6BSd \cdot d_{ff}
Block totalβ‰ˆ8BSd2+4BS2d+6BSdβ‹…dff\approx 8BSd^2 + 4BS^2d + 6BSd \cdot d_{ff}

For the full model with LL layers:

ForwardΒ FLOPsβ‰ˆLΓ—(8BSd2+4BS2d+6BSdβ‹…dff)\text{Forward FLOPs} \approx L \times (8BSd^2 + 4BS^2d + 6BSd \cdot d_{ff})

Training FLOPs β‰ˆ 3Γ— forward (1Γ— forward + 2Γ— backward).

For LLaMA-2-7B (d=4096,dff=11008,L=32,S=2048,B=1d=4096, d_{ff}=11008, L=32, S=2048, B=1):

  • Per-token: ~14 GFLOPs
  • Full sequence: ~28 TFLOPs
  • The S2S^2 term (attention) is small at S=2048S=2048 but dominates at S=128KS=128K+

6. Why Decoder-Only Won

The original Transformer (2017) had both an encoder and decoder. Three architecture families emerged:

ArchitectureExamplesDesignStatus
Encoder-onlyBERT, RoBERTaBidirectional attention, masked token predictionSuperseded for generation
Encoder-DecoderT5, BARTEncoder processes input, decoder generates outputUsed for translation, summarization
Decoder-onlyGPT, LLaMA, QwenCausal attention, next-token predictionDominant for LLMs

Why decoder-only won:

  1. Simpler: one architecture for both understanding and generation β€” no separate encoder
  2. Scalable: just stack more identical blocks. No encoder-decoder cross-attention complexity
  3. Unified pretraining: next-token prediction works for every task when prompted correctly
  4. Efficient inference: KV cache works naturally with causal attention; encoder-decoder requires managing two caches

Every major production LLM today (GPT-4, Claude, LLaMA, Qwen, Mistral, DeepSeek) is decoder-only.


7. Depth vs Width: Scaling Dimensions

When scaling a model from 7B to 70B to 400B+, which dimensions change?

Dimension7B (LLaMA-2)70B (LLaMA-2)405B (LLaMA-3.1)Scaling pattern
$ (hidden)4,0968,19216,384~4Γ—
$ (layers)3280126~4Γ—
$ (heads)3264128~4Γ—
$ (head dim)128128128Constant
{ff}$11,00828,67253,248Scales with $

Key patterns:

  • Head dimension stays fixed at 128 β€” universally. More capacity = more heads, not bigger heads.
  • Depth and width scale together β€” roughly doubling both gives ~8Γ— parameters.
  • Width affects per-layer cost quadratically (^2$ in attention projections) while depth affects cost linearly (more layers, same cost each).
  • Depth gives more representational layers (more processing steps), width gives more capacity per layer (higher-dimensional representations).

In practice, scaling both gives the best quality per FLOP β€” this is what scaling laws predict.


Self-Check

  • Trace the shape of a tensor through a complete forward pass (embedding β†’ L blocks β†’ logits)
  • Explain why the hidden dimension dd is preserved through all blocks
  • Explain the causal mask and why it prevents attending to future tokens
  • Explain SwiGLU vs standard FFN (3 matrices vs 2, activation function)
  • Calculate parameter count for a given model config
  • Explain why dk=128d_k = 128 is universal and dffβ‰ˆ(8/3)dd_{ff} \approx (8/3)d with SwiGLU
  • Explain GQA and how it reduces KV cache
  • Estimate forward FLOPs for a given model and sequence length

References