RMSNorm and SwiGLU: Mathematical Foundations of Scaling-Invariant Normalization, Gated Activations, and FFN Architectures in Modern LLMs

The architectural baseline of modern autoregressive large language models has converged on a distinct set of mathematical primitives. While early Transformer architectures relied on standard Layer Normalization, Post-LN residual routing, and two-layer Multi-Layer Perceptrons with ReLU or GELU activations, state-of-the-art open-weights models such as LLaMA, Mistral, Gemma, Qwen, and DeepSeek utilize a different combination: Root Mean Square Layer Normalization (RMSNorm), Pre-LN residual connectio

10 min
RMSNorm and SwiGLU: Mathematical Foundations of Scaling-Invariant Normalization, Gated Activations, and FFN Architectures in Modern LLMs

The architectural baseline of modern autoregressive large language models has converged on a distinct set of mathematical primitives. While early Transformer architectures relied on standard Layer Normalization, Post-LN residual routing, and two-layer Multi-Layer Perceptrons with ReLU or GELU activations, state-of-the-art open-weights models such as LLaMA, Mistral, Gemma, Qwen, and DeepSeek utilize a different combination: Root Mean Square Layer Normalization (RMSNorm), Pre-LN residual connections, and Gated Linear Unit feed-forward networks (specifically SwiGLU), typically implemented with zero additive bias parameters.

These architectural modifications are not arbitrary heuristic tweaks. They are mathematically grounded adjustments designed to optimize gradient propagation, reduce memory bandwidth overhead on modern GPU architectures, and increase the representational capacity of feed-forward layers at constant computational budgets.

Layer Normalization vs. RMSNorm: Mathematical Formulations

Standard Layer Normalization, introduced by Ba, Kiros, and Hinton (2016), normalizes activations across the feature dimension dd for each token vector xRdx \in \mathbb{R}^d. The standard formulation computes both the mean and variance across the hidden dimensions:

μ=1di=1dxi\mu = \frac{1}{d} \sum_{i=1}^d x_i

σ=1di=1d(xiμ)2+ϵ\sigma = \sqrt{\frac{1}{d} \sum_{i=1}^d (x_i - \mu)^2 + \epsilon}

x^=xμσγ+β\hat{x} = \frac{x - \mu}{\sigma} \odot \gamma + \beta

Here, γRd\gamma \in \mathbb{R}^d and βRd\beta \in \mathbb{R}^d are learnable scale (gain) and shift (bias) parameters, and ϵ>0\epsilon > 0 is a small numerical stabilizer.

The RMSNorm Formulation

In their analysis of Layer Normalization, Zhang and Sennrich (2019) investigated the theoretical components responsible for training stabilization in deep networks. They demonstrated that the computational benefit of LayerNorm stems almost entirely from scaling invariance rather than shift invariance (mean-centering).

RMSNorm replaces standard variance normalization with the root mean square statistic, discarding mean computation entirely:

RMS(x)=1di=1dxi2+ϵ\text{RMS}(x) = \sqrt{\frac{1}{d} \sum_{i=1}^d x_i^2 + \epsilon}

xˉ=xRMS(x)γ\bar{x} = \frac{x}{\text{RMS}(x)} \odot \gamma

In RMSNorm, the shift parameter β\beta is removed, leaving only the learnable gain parameter γRd\gamma \in \mathbb{R}^d.

LayerNorm:
  x ───> [ Compute Mean μ ] ───> [ Subtract Mean (x - μ) ] ───> [ Compute Variance σ² ] ───> [ Scale & Shift (γ, β) ] ───> Output

RMSNorm:
  x ───────────────────────────> [ Compute RMS(x) ] ──────────> [ Normalize & Scale (γ) ] ─────────────────────────> Output

Invariance Properties and Hardware Efficiency

LayerNorm provides two distinct invariance properties:

  1. Shift invariance: LN(x+c)=LN(x)\text{LN}(x + c) = \text{LN}(x) for any constant offset scalar cc.
  2. Scaling invariance: LN(αx)=LN(x)\text{LN}(\alpha x) = \text{LN}(x) for any positive scaling scalar α>0\alpha > 0.

Zhang and Sennrich showed that the gradient regularization effect that prevents vanishing and exploding gradients in deep networks is governed by the scaling invariance property. Shift invariance has negligible impact on training dynamics across deep Transformer models.

Removing the mean computation provides significant advantages for GPU kernel execution:

  • Elimination of redundant reduction passes: Standard LayerNorm requires two reduction passes across the hidden dimension (one to calculate the mean μ\mu, and a second to calculate the variance σ2\sigma^2). RMSNorm requires only a single reduction pass to compute the sum of squares.
  • Memory bandwidth reduction: In fused CUDA and Triton kernels, avoiding the intermediate subtraction pass reduces registers per thread and minimizes SRAM/HBM round trips. This delivers a 10% to 50% execution speedup for the normalization kernel itself, which directly impacts training and inference throughput since normalization executes twice per Transformer block.

Normalization Placement: Pre-LN and Gradient Stability

The placement of normalization layers relative to the residual stream dictates gradient propagation through deep networks.

Post-LN Dynamics

The original Transformer architecture by Vaswani et al. (2017) placed normalization after the residual addition:

xl+1=Norm(xl+SubLayer(xl))x_{l+1} = \text{Norm}(x_l + \text{SubLayer}(x_l))

In Post-LN architectures, the gradient backpropagated from layer LL to layer ll is scaled by the product of normalization derivatives across all intermediate layers:

xLxl=k=lL1(Norm(zk)zk(I+SubLayer(xk)xk))\frac{\partial x_L}{\partial x_l} = \prod_{k=l}^{L-1} \left( \frac{\partial \text{Norm}(z_k)}{\partial z_k} \left( I + \frac{\partial \text{SubLayer}(x_k)}{\partial x_k} \right) \right)

As network depth increases, the normalization gradient scaling causes vanishing gradients in early layers during initialization. Consequently, Post-LN models require carefully tuned learning rate warmup schedules to prevent optimization divergence.

Pre-LN and the Identity Highway

Modern LLMs universally adopt Pre-LN (specifically Pre-RMSNorm):

xl+1=xl+SubLayer(RMSNorm(xl))x_{l+1} = x_l + \text{SubLayer}(\text{RMSNorm}(x_l))

By placing RMSNorm on the branch of the sublayer before the transformation, the residual connection forms an unobstructed identity path:

xLxl=I+k=lL1SubLayer(RMSNorm(xk))xl\frac{\partial x_L}{\partial x_l} = I + \sum_{k=l}^{L-1} \frac{\partial \text{SubLayer}(\text{RMSNorm}(x_k))}{\partial x_l}

The leading identity term II ensures that gradients flow back to early layers without attenuation or explosion, allowing stable training of models with 100+ layers without delicate warmup dependencies.

Feed-Forward Networks: From Standard MLPs to Gated Linear Units

In standard Transformer architectures, the feed-forward network (FFN) consists of two linear projections with an element-wise non-linear activation function in between:

FFNStandard(x)=σ(xW1+b1)W2+b2\text{FFN}_{\text{Standard}}(x) = \sigma(x W_1 + b_1) W_2 + b_2

Where W1Rdmodel×dffW_1 \in \mathbb{R}^{d_{\text{model}} \times d_{\text{ff}}}, W2Rdff×dmodelW_2 \in \mathbb{R}^{d_{\text{ff}} \times d_{\text{model}}}, and σ\sigma is typically ReLU or Gaussian Error Linear Unit (GELU), as introduced by Hendrycks and Gimpel (2016). Standard configurations set dff=4dmodeld_{\text{ff}} = 4 d_{\text{model}}, yielding a parameter count of 8dmodel28 d_{\text{model}}^2 (ignoring bias vectors).

<img src="https://cms.llms.blog/content/images/2026/08/swiglu-gated-architecture.png" alt="SwiGLU Gated Linear Unit Architecture" />

Gated Linear Units (GLU)

Dauphin et al. (2016) introduced Gated Linear Units for sequence modeling in convolutional networks. A GLU replaces the static activation function with a component-wise product of two distinct linear projections, one of which is modulated by a gating function:

GLU(x,W,V)=σ(xW)(xV)\text{GLU}(x, W, V) = \sigma(x W) \otimes (x V)

Where \otimes denotes element-wise (Hadamard) multiplication, WW is the gating projection, and VV is the value (or up) projection.

Shazeer's GLU Variants: ReGLU, GEGLU, and SwiGLU

Noam Shazeer (2020) extended the GLU formulation to Transformer feed-forward sublayers by exploring different non-linear activation functions in place of the standard sigmoid σ\sigma:

ReGLU(x,W,V)=max(0,xW)(xV)\text{ReGLU}(x, W, V) = \max(0, x W) \otimes (x V)

GEGLU(x,W,V)=GELU(xW)(xV)\text{GEGLU}(x, W, V) = \text{GELU}(x W) \otimes (x V)

SwiGLU(x,W,V,β)=Swishβ(xW)(xV)\text{SwiGLU}(x, W, V, \beta) = \text{Swish}_\beta(x W) \otimes (x V)

The Swish activation function, identified by Ramachandran, Zoph, and Le (2017) via automated search (also known as the Sigmoid Linear Unit or SiLU when β=1\beta=1), is defined as:

Swishβ(z)=zsigmoid(βz)=z1+eβz\text{Swish}_\beta(z) = z \cdot \text{sigmoid}(\beta z) = \frac{z}{1 + e^{-\beta z}}

For modern LLM implementations, β=1\beta = 1 is standard, reducing the activation to SiLU(z)=zσ(z)\text{SiLU}(z) = z \cdot \sigma(z).

The complete SwiGLU feed-forward layer consists of three linear transformations:

FFNSwiGLU(x)=(SiLU(xWgate)(xWup))Wdown\text{FFN}_{\text{SwiGLU}}(x) = \left( \text{SiLU}(x W_{\text{gate}}) \odot (x W_{\text{up}}) \right) W_{\text{down}}

Where:

  • WgateRdmodel×dffW_{\text{gate}} \in \mathbb{R}^{d_{\text{model}} \times d_{\text{ff}}} projects the input into the gating path.
  • WupRdmodel×dffW_{\text{up}} \in \mathbb{R}^{d_{\text{model}} \times d_{\text{ff}}} projects the input into the value path.
  • WdownRdff×dmodelW_{\text{down}} \in \mathbb{R}^{d_{\text{ff}} \times d_{\text{model}}} projects the gated intermediate representation back to the model hidden dimension.

Parameter Balancing and Dimensioning

A standard two-matrix FFN with hidden dimension dff_std=4dmodeld_{\text{ff\_std}} = 4 d_{\text{model}} contains:

ParamsStandard=2dmodeldff_std=8dmodel2\text{Params}_{\text{Standard}} = 2 \cdot d_{\text{model}} \cdot d_{\text{ff\_std}} = 8 d_{\text{model}}^2

Because SwiGLU introduces a third weight matrix (WgateW_{\text{gate}}, WupW_{\text{up}}, and WdownW_{\text{down}}), the total parameter count for a hidden dimension dffd_{\text{ff}} becomes:

ParamsSwiGLU=3dmodeldff\text{Params}_{\text{SwiGLU}} = 3 \cdot d_{\text{model}} \cdot d_{\text{ff}}

To keep the computational and parameter cost equivalent to a standard 4dmodel4 d_{\text{model}} FFN, the intermediate dimension dffd_{\text{ff}} must be adjusted:

3dmodeldff=8dmodel2    dff=83dmodel2.667dmodel3 \cdot d_{\text{model}} \cdot d_{\text{ff}} = 8 d_{\text{model}}^2 \implies d_{\text{ff}} = \frac{8}{3} d_{\text{model}} \approx 2.667 d_{\text{model}}

Hardware-Aligned Dimensioning in Production

In production architectures such as Meta's LLaMA series (Touvron et al., 2023), dffd_{\text{ff}} is calculated using the 83dmodel\frac{8}{3} d_{\text{model}} ratio and subsequently rounded up to a multiple of 256 or 64.

This rounding ensures that matrix dimensions align with the warp tile dimensions of NVIDIA Tensor Cores (such as 16×16×1616 \times 16 \times 16 or 16×8×3216 \times 8 \times 32 MMA operations), preventing execution divergence and padding overhead in matrix multiplications:

dff=25683dmodel256d_{\text{ff}} = 256 \cdot \left\lceil \frac{\frac{8}{3} d_{\text{model}}}{256} \right\rceil

For example, in a model with dmodel=4096d_{\text{model}} = 4096, the theoretical 83dmodel\frac{8}{3} d_{\text{model}} is approximately 10922.6710922.67. Rounding to the nearest multiple of 256 yields dff=11008d_{\text{ff}} = 11008. Some configurations (such as LLaMA-3 8B) scale dffd_{\text{ff}} even higher to 1433614336 (a 3.5dmodel\approx 3.5 d_{\text{model}} ratio) to allocate higher parameter capacity to the FFN sublayers while keeping attention parameter footprints fixed.

Why SwiGLU Outperforms Traditional Activations

Empirical benchmarks across large-scale pre-training runs consistently show that SwiGLU achieves lower validation perplexity than ReLU, GELU, and classical GLU at equivalent compute budgets. Several mathematical characteristics explain this performance advantage:

1. Dynamic Multiplicative Gating

In standard FFNs, activation functions apply a static scalar non-linearity to each channel independently: yi=σ(zi)y_i = \sigma(z_i). In SwiGLU, the value projection xWupx W_{\text{up}} is dynamically scaled by SiLU(xWgate)\text{SiLU}(x W_{\text{gate}}). The gating vector acts as a continuous, input-dependent filter that can selectively suppress or amplify specific feature channels based on context.

2. Smooth, Non-Monotonic Gradient Landscape

The SiLU activation function is smooth and non-monotonic:

SiLU(z)=z1+ez\text{SiLU}(z) = \frac{z}{1 + e^{-z}}

Its first derivative with respect to zz is:

ddzSiLU(z)=σ(z)+zσ(z)(1σ(z))=σ(z)(1+z(1σ(z)))\frac{d}{dz}\text{SiLU}(z) = \sigma(z) + z \sigma(z)(1 - \sigma(z)) = \sigma(z) \left( 1 + z(1 - \sigma(z)) \right)

For positive values (z0z \gg 0), ddzSiLU(z)1\frac{d}{dz}\text{SiLU}(z) \approx 1. For large negative values (z0z \ll 0), ddzSiLU(z)0\frac{d}{dz}\text{SiLU}(z) \approx 0. Crucially, for moderately negative values (near z1.28z \approx -1.28), SiLU dips slightly below zero to a minimum of approximately 0.278-0.278, and its derivative is non-zero.

Unlike ReLU, which has a hard zero derivative for all negative inputs (leading to irreversible neuron death during training), SiLU allows small gradient signals to propagate back through negative pre-activations, preserving optimization flexibility.

Activation Value Comparison:
  z = -3.0  --> ReLU(z) = 0.000, GELU(z) ≈ -0.004, SiLU(z) ≈ -0.142
  z = -1.0  --> ReLU(z) = 0.000, GELU(z) ≈ -0.159, SiLU(z) ≈ -0.269
  z =  0.0  --> ReLU(z) = 0.000, GELU(z) =  0.000, SiLU(z) =  0.000
  z =  1.0  --> ReLU(z) = 1.000, GELU(z) ≈  0.841, SiLU(z) ≈  0.731
  z =  3.0  --> ReLU(z) = 3.000, GELU(z) ≈  2.996, SiLU(z) ≈  2.858

3. Bilinear Higher-Order Interactions

The product SiLU(xWgate)(xWup)\text{SiLU}(x W_{\text{gate}}) \odot (x W_{\text{up}}) introduces quadratic interaction terms between the linear projections of xx. A single SwiGLU layer can compute second-order polynomial combinations of input features, providing significantly richer representational capacity than standard affine transformations followed by univariate non-linearities.

Elimination of Additive Bias Parameters

A complementary trend across modern architectures (LLaMA, Mistral, Gemma 2, Qwen2.5) is the complete removal of additive bias terms (b=0b = 0) across all projection matrices and normalization layers:

  • Attention projections: Q=xWQ,K=xWK,V=xWV,O=AttnWOQ = x W_Q, \quad K = x W_K, \quad V = x W_V, \quad O = \text{Attn} \cdot W_O
  • SwiGLU projections: $\text{Gate} = x W_{\text{gate}}, \quad \text{Up} = x W_{\text{up}}, \quad \text{Down} = \text{Inter} \cdot W_{\text{down}}$
  • Normalization: y=xRMS(x)γy = \frac{x}{\text{RMS}(x)} \odot \gamma

Eliminating bias terms provides three concrete benefits:

  1. Memory overhead: Reduces optimizer state memory (e.g., in AdamW, each parameter requires 8 additional bytes for first and second moments).
  2. Quantization stability: Additive biases frequently accumulate systematic offset errors during low-precision post-training quantization (such as FP8, INT8, and INT4 weight-only schemes). Zero-bias matrices produce activation distributions centered around zero, reducing asymmetric clipping errors.
  3. Long-context extrapolation: Bias terms in linear projections can cause hidden state magnitudes to drift monotonically as sequence lengths scale into tens of thousands of tokens.

PyTorch Reference Implementation

The following module implements Pre-RMSNorm and a zero-bias SwiGLU feed-forward layer compatible with modern open-weights architectures:

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

class RMSNorm(nn.Module):
    """
    Root Mean Square Layer Normalization (RMSNorm).
    Reference: Zhang & Sennrich (2019) - https://arxiv.org/abs/1910.07467
    """
    def __init__(self, dim: int, eps: float = 1e-6):
        super().__init__()
        self.eps = eps
        self.weight = nn.Parameter(torch.ones(dim))

    def _norm(self, x: torch.Tensor) -> torch.Tensor:
        # Compute root mean square along the last dimension
        return x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        output = self._norm(x.float()).type_as(x)
        return output * self.weight

class SwiGLUFeedForward(nn.Module):
    """
    SwiGLU Feed-Forward Network with zero-bias linear projections.
    Reference: Shazeer (2020) - https://arxiv.org/abs/2002.05202
    """
    def __init__(self, d_model: int, d_ff: int | None = None, multiple_of: int = 256):
        super().__init__()
        # If d_ff is not provided, calculate 8/3 * d_model rounded to multiple_of
        if d_ff is None:
            d_ff = int(2 * (4 * d_model) / 3)
            d_ff = multiple_of * ((d_ff + multiple_of - 1) // multiple_of)

        self.w_gate = nn.Linear(d_model, d_ff, bias=False)
        self.w_up = nn.Linear(d_model, d_ff, bias=False)
        self.w_down = nn.Linear(d_ff, d_model, bias=False)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        # SwiGLU: (SiLU(x * W_gate) * (x * W_up)) * W_down
        return self.w_down(F.silu(self.w_gate(x)) * self.w_up(x))

class TransformerBlock(nn.Module):
    """
    Pre-RMSNorm Transformer Block with SwiGLU FFN.
    """
    def __init__(self, d_model: int, num_heads: int):
        super().__init__()
        self.attention_norm = RMSNorm(d_model)
        self.attention = nn.MultiheadAttention(d_model, num_heads, bias=False, batch_first=True)
        self.ffn_norm = RMSNorm(d_model)
        self.ffn = SwiGLUFeedForward(d_model)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        # Pre-LN Attention residual branch
        normed_attn_in = self.attention_norm(x)
        attn_out, _ = self.attention(normed_attn_in, normed_attn_in, normed_attn_in)
        x = x + attn_out

        # Pre-LN SwiGLU residual branch
        x = x + self.ffn(self.ffn_norm(x))
        return x

Summary Comparison

The shift from first-generation Transformer layers to modern architectural primitives is summarized below:

  • Normalization algorithm: LayerNorm (with mean subtraction and variance normalization) replaced by RMSNorm (scaling by root mean square alone).
  • Normalization parameters: Scale γ\gamma and shift β\beta replaced by scale γ\gamma only.
  • Normalization topology: Post-LN replaced by Pre-LN to maintain an unattenuated identity gradient highway.
  • FFN activation function: ReLU / GELU replaced by SwiGLU (SiLU(xWgate)xWup\text{SiLU}(x W_{\text{gate}}) \odot x W_{\text{up}}).
  • FFN projection count: 2 matrices (W1,W2W_1, W_2) replaced by 3 matrices (Wgate,Wup,WdownW_{\text{gate}}, W_{\text{up}}, W_{\text{down}}).
  • Intermediate FFN dimension: 4dmodel4 d_{\text{model}} adjusted to 83dmodel\frac{8}{3} d_{\text{model}} (rounded to multiples of 256) to maintain parameter parity.
  • Bias parameters: Explicit bias vectors across attention, FFN, and normalization removed (b=0b = 0).

Sources

Written by

More to read

  • Real-Time Voice AI Agent Frameworks in Production: Comparing LiveKit Agents, Pipecat, OpenAI Realtime API, and Ultravox

    Real-Time Voice AI Agent Frameworks in Production: Comparing LiveKit Agents, Pipecat, OpenAI Realtime API, and Ultravox Deploying conversational voice agents in production requires solving a fundamental physics and networking problem: human conversational turn-taking occurs within an average gap of 200 to 300 milliseconds. When an artificial conversational agent exceeds 600 to 800 milliseconds of round-trip latency, users perceive the interaction as sluggish, talk over the assistant, or experie

    1 min
  • Nvidia Pauses Selected Revenue-Sharing Deals with AI Cloud Providers

    Nvidia has paused select partnership deals under its newly introduced AI cloud financing initiative, according to reporting by The Wall Street Journal. The program, unveiled in July 2026, was designed to provide credit support and hardware access to emerging cloud computing providers in exchange for a percentage of future recurring revenues. While Nvidia stated that the broader program remains operational, several individual agreements have been put on hold as the company reassesses customer te

    1 min
  • Claude Code Opus 5 Auto Mode Bypassed via Python Module Shadowing Exploit

    Security researcher Johann Rehberger has published technical details on a multi-stage exploit chain that achieves arbitrary code execution against Claude Code Opus 5 running in Auto Mode. The attack demonstrates how adversarial files can bypass Anthropic's safety classifiers and prompt injection defenses by exploiting standard runtime behavior in Python. Anthropic rolled out Auto Mode as the default starting mode for Claude Code in mid-August 2026. Auto Mode replaces explicit human permission p

    1 min