DEV Community

Shrijith Venkatramana
Shrijith Venkatramana

Posted on

RMSNorm and SwiGLU: Two Small Ideas That Changed the Transformer

Hello, I'm Shrijith Venkatramana. I'm building git-lrc, an AI code reviewer that runs on every commit. Star Us to help devs discover the project. Do give it a try and share your feedback for improving the product.


If you open the implementation of a modern LLM, the interesting part is often hidden in a handful of lines.

There is the attention mechanism, which gets most of the attention. Then there are two components that look almost embarrassingly simple:

x = x * rsqrt(mean(x^2) + eps)
Enter fullscreen mode Exit fullscreen mode

and

y = W2 * (Swish(W1 * x) * W3 * x)
Enter fullscreen mode Exit fullscreen mode

The first is RMSNorm.

The second is SwiGLU.

Together, they are part of the architecture that became characteristic of models such as LLaMA and its descendants. Meta's Llama 2 technical report describes a decoder-only Transformer using pre-normalization with RMSNorm and SwiGLU feed-forward layers.

Neither idea is particularly complicated.

The interesting engineering story is why these simple operations work so well, why they displaced older choices such as LayerNorm + ReLU/GELU, and what their arithmetic looks like when you scale them to billions of parameters and trillions of tokens.

This article builds the intuition first, then gets into the equations, parameter economics, and implementation details.

1. First, where do RMSNorm and SwiGLU actually live?

A Transformer block roughly looks like this:

             ┌──────────────────────┐
             │      Attention       │
             └──────────────────────┘
                       │
                       v
                  RMSNorm
                       │
                       v
             ┌──────────────────────┐
             │       SwiGLU         │
             │        FFN           │
             └──────────────────────┘
                       │
                       v
                    output
Enter fullscreen mode Exit fullscreen mode

A modern pre-norm Transformer is more precisely something like:

h1 = x + Attention(RMSNorm(x))

h2 = h1 + SwiGLU(RMSNorm(h1))
Enter fullscreen mode Exit fullscreen mode

The two components solve very different problems.

RMSNorm controls the scale of representations.

As information passes through dozens or hundreds of Transformer blocks, activations can acquire wildly different magnitudes. RMSNorm keeps their overall scale under control.

SwiGLU provides nonlinear computation.

Attention lets tokens communicate with one another. The FFN processes each token's representation independently and gives the network substantial computational capacity for transforming that representation.

This distinction is useful:

Attention  -> "Which information should I retrieve?"
SwiGLU     -> "How should I transform this information?"
RMSNorm    -> "Keep the representation numerically well behaved."
Enter fullscreen mode Exit fullscreen mode

The modern LLM stack therefore isn't just "attention."

A considerable amount of the model's computation happens in the FFN.

And that makes the design of the FFN extremely important.

2. RMSNorm: LayerNorm with one operation removed

Let's start with the older and more familiar idea.

Suppose a hidden vector is:

x = [2, 4, 6, 8]
Enter fullscreen mode Exit fullscreen mode

LayerNorm computes the mean:

mean(x) = 5
Enter fullscreen mode Exit fullscreen mode

and the variance:

variance(x)
    = ((2-5)^2 + (4-5)^2 + (6-5)^2 + (8-5)^2) / 4
    = 5
Enter fullscreen mode Exit fullscreen mode

Then it transforms each value roughly as:

x_normalized = (x - mean) / sqrt(variance + eps)
Enter fullscreen mode Exit fullscreen mode

So LayerNorm does two things:

1. subtract the mean
2. divide by the standard deviation
Enter fullscreen mode Exit fullscreen mode

RMSNorm asks a surprisingly provocative question:

Do we actually need the first operation?

Biao Zhang and Rico Sennrich asked essentially this question in their 2019 paper, Root Mean Square Layer Normalization. Their argument was that re-centering the activations around zero may be unnecessary.

Instead of calculating variance around the mean, RMSNorm calculates the root mean square:

RMS(x) = sqrt( (x1^2 + x2^2 + ... + xd^2) / d )
Enter fullscreen mode Exit fullscreen mode

and normalizes:

RMSNorm(x) = gamma * x / sqrt(mean(x^2) + eps)
Enter fullscreen mode Exit fullscreen mode

where gamma is a learned scale vector.

That's it.

There is no:

mean = sum(x) / d
x - mean
Enter fullscreen mode Exit fullscreen mode

operation.

This matters at scale because normalization is performed constantly.

The original RMSNorm paper reported comparable performance to LayerNorm while reducing running time by 7% to 64% across the models they tested.

The exact speedup depends heavily on the surrounding architecture and implementation, but the basic engineering attraction is obvious:

LayerNorm:

mean
  ↓
subtract
  ↓
square
  ↓
variance
  ↓
sqrt
  ↓
scale

RMSNorm:

square
  ↓
mean
  ↓
sqrt
  ↓
scale
Enter fullscreen mode Exit fullscreen mode

One statistical operation disappeared.

3. The intuition behind RMSNorm

Consider two vectors:

A = [1, 2, 3, 4]

B = [101, 102, 103, 104]
Enter fullscreen mode Exit fullscreen mode

They have the same shape but very different offsets.

LayerNorm treats the offset as something to remove.

RMSNorm doesn't.

Instead, it asks:

How large is this vector overall?

For A:

mean(square(A))
    = (1 + 4 + 9 + 16) / 4
    = 7.5

RMS(A) = sqrt(7.5)
       ~= 2.74
Enter fullscreen mode Exit fullscreen mode

So:

A / RMS(A)
 ~= [0.36, 0.73, 1.09, 1.46]
Enter fullscreen mode Exit fullscreen mode

The operation preserves the direction of the vector while controlling its magnitude.

This gives a useful geometric interpretation.

Imagine a high-dimensional vector as an arrow.

RMSNorm approximately says:

          x
          |
          |       x
          |     /
          |   /
          | /
----------+----------------
Enter fullscreen mode Exit fullscreen mode

Keep the direction.

Normalize the length.

The learned gamma then allows the network to decide how much scale each feature should ultimately receive.

This is particularly attractive in a deep residual network.

A Transformer repeatedly performs operations like:

x -> x + f(x)
Enter fullscreen mode Exit fullscreen mode

If the magnitude of f(x) continually changes relative to x, optimization can become difficult.

RMSNorm provides a recurring scale-control mechanism.

There is also an interesting theoretical interpretation in the original paper: RMSNorm has an implicit adaptive-learning-rate-like effect because its normalization depends on the magnitude of the current activation.

4. Why RMSNorm became particularly interesting for LLMs

The original RMSNorm paper predates the current LLM explosion.

The idea was proposed in 2019, when large Transformer language models were already emerging but the modern LLM ecosystem was still several years away.

Then the architectural pieces started converging.

The Transformer appeared in 2017.

T5 explored large-scale Transformer language modeling and heavily influenced later architectures.

Noam Shazeer investigated gated FFNs.

Zhang and Sennrich investigated RMSNorm.

Meta's LLaMA architecture subsequently combined several of these ideas into a compact decoder-only design.

Llama 2, for example, uses RMSNorm and SwiGLU in its Transformer blocks.

This is one of the interesting patterns in deep learning architecture:

Research paper
      ↓
small architectural modification
      ↓
empirical validation
      ↓
adoption by a major model
      ↓
becomes "obvious" architecture
      ↓
eventually becomes boilerplate code
Enter fullscreen mode Exit fullscreen mode

By the time you encounter:

self.norm = RMSNorm(dim)
Enter fullscreen mode Exit fullscreen mode

in a LLaMA implementation, you're looking at the endpoint of several years of experimentation.

5. SwiGLU: the feed-forward network gets a gate

Now consider the other half.

The original Transformer FFN was conceptually simple:

FFN(x) = W2 * ReLU(W1 * x)
Enter fullscreen mode Exit fullscreen mode

There are two linear projections.

The first expands the representation.

The activation introduces nonlinearity.

The second projects it back down.

For example:

hidden size = 4096
FFN size    = 16384
Enter fullscreen mode Exit fullscreen mode

The representation gets expanded:

4096 -> 16384 -> 4096
Enter fullscreen mode Exit fullscreen mode

Why expand it?

Because the intermediate layer provides a large computational workspace.

A useful analogy is a temporary scratchpad.

The model takes a 4096-dimensional representation, expands it into a much larger space, performs nonlinear computation there, and compresses it back.

But there is a problem with a conventional activation such as ReLU.

ReLU is:

ReLU(x) = max(0, x)
Enter fullscreen mode Exit fullscreen mode

It makes a hard decision:

negative -> 0
positive -> x
Enter fullscreen mode Exit fullscreen mode

Shazeer's 2020 paper GLU Variants Improve Transformer explored a different idea: gating.

Instead of simply activating a projection, construct two projections:

a = W1 * x

b = W3 * x
Enter fullscreen mode Exit fullscreen mode

Apply a nonlinear function to one:

g = activation(a)
Enter fullscreen mode Exit fullscreen mode

Then multiply:

h = g * b
Enter fullscreen mode Exit fullscreen mode

The second projection acts like a learned gate.

This creates a powerful mechanism:

input
  |
  +----> projection A ---> activation ---+
  |                                       |
  +----> projection B --------------------*----> output projection
Enter fullscreen mode Exit fullscreen mode

Each dimension can effectively modulate another dimension.

That's the core GLU idea.


6. Why SwiGLU?

Shazeer tested several GLU variants, including:

GLU
ReGLU
GEGLU
SwiGLU
Enter fullscreen mode Exit fullscreen mode

The activation in SwiGLU is the SiLU/Swish function:

SiLU(x) = x * sigmoid(x)
Enter fullscreen mode Exit fullscreen mode

where:

sigmoid(x) = 1 / (1 + exp(-x))
Enter fullscreen mode Exit fullscreen mode

Therefore:

SwiGLU(x)
    = SiLU(W1 * x) * (W3 * x)

    = [W1*x * sigmoid(W1*x)] * [W3*x]
Enter fullscreen mode Exit fullscreen mode

followed by the output projection:

FFN(x) = W2 * (SiLU(W1*x) * (W3*x))
Enter fullscreen mode Exit fullscreen mode

Notice something important.

A conventional FFN has two matrices:

W1
W2
Enter fullscreen mode Exit fullscreen mode

SwiGLU has three:

W1
W2
W3
Enter fullscreen mode Exit fullscreen mode

That sounds like a 50% increase in parameters.

And it would be, if we kept exactly the same intermediate dimension.

Shazeer's experiments instead reduced the intermediate dimension so that the total parameter count stayed approximately constant.

This is one of the most important implementation details.

7. The 2/3 rule and the economics of SwiGLU

Suppose a conventional FFN has:

d_model = 4096
d_ff    = 16384
Enter fullscreen mode Exit fullscreen mode

Ignoring biases, its parameter count is approximately:

W1: 4096 * 16384
W2: 16384 * 4096

total = 2 * 4096 * 16384
      ~= 134.2 million parameters
Enter fullscreen mode Exit fullscreen mode

Now suppose we naïvely introduce SwiGLU with the same d_ff.

We have three matrices:

W1: 4096 * 16384
W2: 16384 * 4096
W3: 4096 * 16384
Enter fullscreen mode Exit fullscreen mode

Total:

3 * 4096 * 16384
~= 201.3 million parameters
Enter fullscreen mode Exit fullscreen mode

That's roughly 50% more.

Instead, choose:

d_ff_swiglu ~= (2/3) * d_ff
Enter fullscreen mode Exit fullscreen mode

So:

d_ff_swiglu ~= 10923
Enter fullscreen mode Exit fullscreen mode

Then:

3 * 4096 * 10923
~= 134.2 million
Enter fullscreen mode Exit fullscreen mode

Approximately the same parameter budget.

This is why you will often see modern architectures with apparently strange FFN dimensions.

For example, instead of thinking:

4096 -> 16384 -> 4096
Enter fullscreen mode Exit fullscreen mode

you might encounter something closer to:

4096 -> 11008 -> 4096
Enter fullscreen mode Exit fullscreen mode

The number is not arbitrary.

It is also frequently rounded to hardware-friendly values such as multiples of 256.

This is where machine-learning architecture meets systems engineering.

A theoretically perfect dimension is irrelevant if it produces ugly GPU kernels.

You care about:

parameter count
FLOPs
memory traffic
tensor-core utilization
kernel shapes
alignment
batch size
Enter fullscreen mode Exit fullscreen mode

A 10,922-wide matrix may have nearly the same mathematical cost as an 11,008-wide matrix, while the latter may map much more conveniently onto the hardware.

8. A concrete LLM block

Let's put the pieces together.

A simplified modern Transformer block can look like:

def block(x):
    h = x + attention(rmsnorm(x))
    h = h + swiglu(rmsnorm(h))
    return h
Enter fullscreen mode Exit fullscreen mode

The RMSNorm is roughly:

def rmsnorm(x, weight, eps=1e-6):
    rms = sqrt(mean(x * x) + eps)
    return weight * x / rms
Enter fullscreen mode Exit fullscreen mode

And SwiGLU:

def swiglu(x):
    a = W1 @ x
    b = W3 @ x
    return W2 @ (silu(a) * b)
Enter fullscreen mode Exit fullscreen mode

There are several implementation details worth noticing.

First, there are no biases in the canonical LLaMA-style FFN.

Second, the two projections into the intermediate dimension happen in parallel.

Third, the elementwise multiplication is extremely cheap relative to the matrix multiplications.

For:

d_model = 4096
d_ff    = 11008
Enter fullscreen mode Exit fullscreen mode

one token requires approximately:

W1: 4096 * 11008
W3: 4096 * 11008
W2: 11008 * 4096
Enter fullscreen mode Exit fullscreen mode

multiply-accumulate operations.

That is roughly:

3 * 45.1M
~= 135M MACs
Enter fullscreen mode Exit fullscreen mode

or approximately:

270M FLOPs
Enter fullscreen mode Exit fullscreen mode

if one multiply-add is counted as two floating-point operations.

And that's per token, per layer, just for the FFN.

For a 32-layer model:

270M * 32
~= 8.6 billion FLOPs/token
Enter fullscreen mode Exit fullscreen mode

The attention mechanism gets the conceptual spotlight, but the FFN is doing enormous amounts of numerical work.

9. What are these components actually buying us?

There is a useful way to think about the two operations.

RMSNorm controls the numerical regime

Without normalization, successive transformations can alter the scale of representations.

RMSNorm gives the network a stable reference:

"Whatever magnitude this representation currently has,
scale it into a predictable range before the next transformation."
Enter fullscreen mode Exit fullscreen mode

SwiGLU increases conditional computation

A standard FFN essentially says:

transform -> activate -> transform
Enter fullscreen mode Exit fullscreen mode

SwiGLU says:

transform A -> nonlinear gate
                   \
                    multiply -> transform
                   /
transform B -------
Enter fullscreen mode Exit fullscreen mode

So the model gets an input-dependent mechanism for controlling information flow through the FFN.

This is subtle.

The gate isn't a separate high-level routing system like a Mixture-of-Experts model.

It is a cheap elementwise interaction inside every token's FFN.

You can think of it as giving every intermediate feature a learned, input-dependent volume knob.

10. Why this matters economically

LLM architecture is ultimately constrained by arithmetic.

Suppose you train a model for:

1 trillion tokens
Enter fullscreen mode Exit fullscreen mode

and your architecture performs an additional:

100 million FLOPs/token
Enter fullscreen mode Exit fullscreen mode

because of an architectural choice.

That's:

100M * 1T
= 1e20 FLOPs
Enter fullscreen mode Exit fullscreen mode

An apparently tiny per-token change becomes enormous at training scale.

The same applies to inference.

If a model generates:

1 billion tokens/day
Enter fullscreen mode Exit fullscreen mode

then an extra:

100M FLOPs/token
Enter fullscreen mode Exit fullscreen mode

means:

1e17 FLOPs/day
Enter fullscreen mode Exit fullscreen mode

So the reason architectural details matter is economic as much as mathematical.

A one-line normalization change can affect:

training stability
kernel complexity
memory bandwidth
latency
power consumption
GPU-hours
Enter fullscreen mode Exit fullscreen mode

And a change to the FFN affects one of the largest computational components of every Transformer layer.

This is why Shazeer's paper is interesting from an engineering perspective.

He wasn't merely inventing another activation function. He was exploring whether a different FFN structure could improve model quality under approximately the same computational and parameter budget.

That constraint is much closer to how production ML actually works.

11. The bigger lesson: modern LLM architecture is evolutionary

There is a funny historical irony here.

When you first learn Transformers, the architecture looks almost inevitable:

Attention
+
Feed Forward
+
Normalization
Enter fullscreen mode Exit fullscreen mode

Modern LLMs make the historical process visible.

The architecture wasn't designed in one shot.

Researchers kept asking small questions:

Do we really need mean-centering?

Can the FFN use a better nonlinearity?

Can a gate improve the representation?

Can we maintain the same parameter budget?

Can we make the operation cheaper?

Does the change survive large-scale experiments?
Enter fullscreen mode Exit fullscreen mode

Zhang and Sennrich proposed RMSNorm in 2019.

Noam Shazeer explored GLU variants in 2020 and found that variants such as SwiGLU and GEGLU could improve Transformer results relative to conventional ReLU/GELU FFNs in his experiments.

A few years later, these ideas appeared together in LLaMA-style architectures. Llama 2, released by Meta in 2023 at 7B through 70B parameter scales, documents this architectural family explicitly.

That is a useful pattern to remember when reading new architecture papers.

The important innovation is frequently hidden inside something that looks too small to deserve its own section.

A new normalization rule.

A different activation.

A changed projection.

A different tensor layout.

A different way of spending the same FLOPs.

At billion-parameter scale, these details compound.


Conclusion: the two lines worth remembering

If you strip away the enormous matrices and billions of parameters, two ideas are remarkably compact.

RMSNorm:

RMS(x) = sqrt(mean(x^2) + eps)

y = gamma * x / RMS(x)
Enter fullscreen mode Exit fullscreen mode

Its job is to control representation scale while avoiding the explicit mean-centering of LayerNorm.

SwiGLU:

SwiGLU(x)
    = W2 * (SiLU(W1*x) * (W3*x))
Enter fullscreen mode Exit fullscreen mode

Its job is to give the FFN an input-dependent gating mechanism while retaining roughly the same parameter/FLOP budget by shrinking the intermediate dimension.

Together they illustrate something important about LLM engineering:

small mathematical change
        +
large number of layers
        +
trillions of tokens
        =
major systems consequence
Enter fullscreen mode Exit fullscreen mode

And perhaps the most interesting part is that neither RMSNorm nor SwiGLU is conceptually exotic.

The difficult engineering question is often:

Which simple operation should a 70-billion-parameter machine perform trillions of times?

If you were designing a Transformer from scratch today, which "boring" component would you investigate first: normalization, activation functions, attention, or the FFN itself?


*AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.

git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.*

Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.

GitHub logo HexmosTech / git-lrc

Free, Micro AI Code Reviews That Run on Git Commit




GenAI today is a race car without brakes. It accelerates fast -- you describe something, and large blocks of code appear instantly. But AI agents silently break things: they remove logic, relax constraints, introduce expensive cloud calls, leak credentials, and change behavior -- without telling you. You often find out in production.

git-lrc is your braking system. It hooks into git commit and runs an AI review on every diff before it lands. 60-second setup. Completely free.

In short, git-lrc helps Prevent Outages, Breaches, and Technical Debt Before They Happen

At a glance: 10 risk categories · 100+ failure patterns tracked · every commit…

Top comments (0)