1. Scaled Dot-Product Attention Mechanics

The Transformer architecture (Vaswani et al. 2017) discards sequential recurrence entirely, computing global contextual dependencies across all sequence tokens simultaneously via Self-Attention.

Given an input sequence representation $\mathbf{X} \in \mathbb{R}^{T \times d_{\text{model}}}$, linear projection matrices $\mathbf{W}_Q, \mathbf{W}_K, \mathbf{W}_V \in \mathbb{R}^{d_{\text{model}} \times d_k}$ generate Queries ($\mathbf{Q}$), Keys ($\mathbf{K}$), and Values ($\mathbf{V}$):

$$\mathbf{Q} = \mathbf{X} \mathbf{W}_Q, \quad \mathbf{K} = \mathbf{X} \mathbf{W}_K, \quad \mathbf{V} = \mathbf{X} \mathbf{W}_V$$

The Scaled Dot-Product Attention computes similarity coefficients across all token pairs:

$$\text{Attention}(\mathbf{Q}, \mathbf{K}, \mathbf{V}) = \text{softmax}\left(\frac{\mathbf{Q} \mathbf{K}^T}{\sqrt{d_k}} + \mathbf{M}\right) \mathbf{V}$$

where $\mathbf{M} \in \mathbb{R}^{T \times T}$ is an optional causal mask where $M_{i,j} = -\infty$ for $j > i$.

Why Scale by $\frac{1}{\sqrt{d_k}}$?

Assume components of $\mathbf{q}_i, \mathbf{k}_j \in \mathbb{R}^{d_k}$ are independent random variables with zero mean and unit variance ($\mathbb{E}[q_m] = \mathbb{E}[k_m] = 0, \; \text{Var}(q_m) = \text{Var}(k_m) = 1$). The dot product $s = \mathbf{q}_i^T \mathbf{k}_j = \sum_{m=1}^{d_k} q_{i,m} k_{j,m}$ has variance:

$$\text{Var}(s) = \sum_{m=1}^{d_k} \text{Var}(q_{i,m} k_{j,m}) = d_k$$

For large embedding dimensions ($d_k \ge 64$), unscaled dot products exhibit extremely high variance ($\sigma = \sqrt{d_k}$), pushing arguments of the Softmax function into saturation regions where gradient magnitudes vanish ($\frac{\partial \text{softmax}(z_i)}{\partial z_j} \approx 0$). Scaling by $\frac{1}{\sqrt{d_k}}$ restores unit variance ($\text{Var}(\frac{s}{\sqrt{d_k}}) = 1$).


2. Multi-Head Attention & Layer Normalization Topology

2.1 Multi-Head Attention (MHA)

To capture heterogeneous relationship subspaces simultaneously, MHA projects queries, keys, and values into $H$ orthogonal attention heads:

$$\text{MultiHead}(\mathbf{Q}, \mathbf{K}, \mathbf{V}) = \text{Concat}(\text{head}_1, \dots, \text{head}_H) \mathbf{W}_O$$$$\text{head}_h = \text{Attention}\left(\mathbf{X} \mathbf{W}_Q^{(h)}, \mathbf{X} \mathbf{W}_K^{(h)}, \mathbf{X} \mathbf{W}_V^{(h)}\right)$$
     Multi-Head Attention & Pre-LN Transformer Block
     
                x_{l+1}
                  ▲
                  │
                 (+) Skip Connection
                  ▲
                  │
               [MLP / FFN]
                  ▲
                  │
              [LayerNorm]
                  ▲
                  │
                 (+) Skip Connection
                  ▲
                  │
        [Multi-Head Attention]
                  ▲
                  │
              [LayerNorm]
                  ▲
                  │
                 x_l

3. Positional Encodings: Sinusoidal vs. Rotary (RoPE)

Since attention operates as a permutation-equivariant set operator, explicit temporal order must be injected into token representations.

3.1 Absolute Sinusoidal Encoding

For token index $t$ and embedding dimension $i$:

$$PE_{(t, 2i)} = \sin\left(\frac{t}{10000^{2i / d_{\text{model}}}}\right), \quad PE_{(t, 2i+1)} = \cos\left(\frac{t}{10000^{2i / d_{\text{model}}}}\right)$$

3.2 Rotary Position Embedding (RoPE - Su et al. 2021)

RoPE encodes relative token distance directly into query-key inner products by rotating complex 2D embedding pairs by angle $m \theta_i$:

$$R_{\Theta, m}^{(i)} = \begin{pmatrix} \cos m\theta_i & -\sin m\theta_i \\ \sin m\theta_i & \cos m\theta_i \end{pmatrix}, \quad \langle \mathbf{R}_m \mathbf{q}_m, \mathbf{R}_n \mathbf{k}_n \rangle = \mathbf{q}_m^T \mathbf{R}_{n-m} \mathbf{k}_n$$

4. FlashAttention: IO-Aware Hardware Tiling

Standard attention computes and materializes the $N \times N$ attention matrix $\mathbf{S} = \mathbf{Q}\mathbf{K}^T$ in GPU High-Bandwidth Memory (HBM), incurring $O(N^2)$ memory reads/writes.

FlashAttention (Dao et al. 2022) computes exact softmax attention using SRAM tiling and online softmax rescaling, eliminating $N \times N$ HBM instantiation and reducing memory complexity from $O(N^2)$ to $O(N)$.


5. PyTorch Implementation: Canonical Pre-LN Causal Transformer Decoder Block

Below is a complete PyTorch implementation of a Canonical Causal Transformer Decoder Block (Pre-LN architecture) standard for modern Large Language Models (LLMs).

import torch
import torch.nn as nn
import torch.nn.functional as F
import math

class CausalSelfAttention(nn.Module):
    """Multi-Head Causal Self-Attention with Pre-LN formulation."""
    def __init__(self, d_model: int = 256, n_heads: int = 8, dropout: float = 0.1):
        super().__init__()
        assert d_model % n_heads == 0, "d_model must be divisible by n_heads"
        self.d_model = d_model
        self.n_heads = n_heads
        self.head_dim = d_model // n_heads
        
        self.qkv_proj = nn.Linear(d_model, 3 * d_model)
        self.out_proj = nn.Linear(d_model, d_model)
        self.dropout = nn.Dropout(dropout)
        
    def forward(self, x: torch.Tensor) -> torch.Tensor:
        B, T, C = x.shape
        qkv = self.qkv_proj(x)
        q, k, v = qkv.chunk(3, dim=-1)
        
        # Reshape to (Batch, Heads, SeqLen, HeadDim)
        q = q.view(B, T, self.n_heads, self.head_dim).transpose(1, 2)
        k = k.view(B, T, self.n_heads, self.head_dim).transpose(1, 2)
        v = v.view(B, T, self.n_heads, self.head_dim).transpose(1, 2)
        
        # Scaled dot-product attention with lower-triangular causal mask
        scale = 1.0 / math.sqrt(self.head_dim)
        attn_scores = torch.matmul(q, k.transpose(-2, -1)) * scale
        
        causal_mask = torch.tril(torch.ones(T, T, dtype=torch.bool, device=x.device))
        attn_scores = attn_scores.masked_fill(~causal_mask, float('-inf'))
        
        attn_weights = F.softmax(attn_scores, dim=-1)
        attn_weights = self.dropout(attn_weights)
        
        context = torch.matmul(attn_weights, v)  # (Batch, Heads, SeqLen, HeadDim)
        context = context.transpose(1, 2).contiguous().view(B, T, C)
        return self.out_proj(context)

class TransformerDecoderBlock(nn.Module):
    """Canonical Pre-LayerNorm Transformer Decoder Block."""
    def __init__(self, d_model: int = 256, n_heads: int = 8, mlp_ratio: int = 4, dropout: float = 0.1):
        super().__init__()
        self.ln1 = nn.LayerNorm(d_model)
        self.attn = CausalSelfAttention(d_model, n_heads, dropout)
        self.ln2 = nn.LayerNorm(d_model)
        
        mlp_hidden = d_model * mlp_ratio
        self.mlp = nn.Sequential(
            nn.Linear(d_model, mlp_hidden),
            nn.GELU(),
            nn.Linear(mlp_hidden, d_model),
            nn.Dropout(dropout)
        )
        
    def forward(self, x: torch.Tensor) -> torch.Tensor:
        x = x + self.attn(self.ln1(x))
        x = x + self.mlp(self.ln2(x))
        return x

# Verification: Forward pass on sequence of token embeddings
if __name__ == "__main__":
    sample_embeddings = torch.randn(8, 64, 256)  # Batch=8, Sequence=64, d_model=256
    block = TransformerDecoderBlock(d_model=256, n_heads=8)
    
    output_representation = block(sample_embeddings)
    print("Input Sequence Embedding Shape:", sample_embeddings.shape)
    print("Output Transformer Block Representation Shape:", output_representation.shape)