PROMETHEUS OS
NATIVE AI OPERATING SYSTEM
[INIT] Prometheus OS loading...
[CORE] Neural interface initializing...
[AI] LLM router connecting...
[MEM] Memory graph loading...
[AGT] Agent chains on standby...
[SEC] Security protocols active...
[NET] Provider mesh established...
[UI] Workspace rendering...
[DONE] All systems nominal.
Welcome to PROMETHEUS OS.
READY · OFFLINE · SECURE · PRIVATE
🎨 THEME ENGINE
PROMETHEUS OS · 23 THEMES
Trial version: Dark + Light themes only.
Full theme access with PROMETHEUS OS license.
Dark theme active
Experience all 23 themes in PROMETHEUS OS

Mixture of Experts

Advanced 14 min· 4 exercises

Understand how mixture-of-experts models route each token to a few specialist sub-networks, and why that makes them fast to run but still hungry for memory.

By the end of this lesson you will be able to
  • Explain how a router sends each token to a few experts and why all experts must stay in memory.
  • Derive softmax top-k gating and compute gate values for given router logits.
  • Compute an MoE model's total and active parameters from its configuration.
  • Implement a top-k router and the Switch-style load-balancing loss in NumPy.
  • Estimate MoE memory needs and decode speed with this site's AI Index formulas and choose between MoE and dense models for given hardware.

Before this: Parameters and Model Size, Transformers: A Deep Dive

Many of the largest open-weight models released in the last two years are mixtures of experts. If you plan to run or pay for AI, this design changes the usual rule that a bigger model is always slower.

The basic idea

A transformer model (the architecture behind today's language models) is a stack of layers. Each layer has an attention part, which lets each token look at earlier tokens, and a feed-forward part, a block of weights that transforms each token's representation. In a dense model, every token passes through the whole feed-forward block of every layer.

A mixture of experts (MoE) replaces that single feed-forward block with many smaller ones called experts, plus a small router (sometimes called a gate). For each token, at each layer, the router scores the experts and sends the token to only the top few. Their outputs are blended and passed on.

An analogy: a large hospital employs hundreds of specialists, but any one patient sees only two or three of them. The hospital still needs room for every specialist, yet each visit takes only the time of the few who are consulted.

A simplification worth flagging: the experts are not neat subject specialists like "the French expert" or "the maths expert". They are learned during training and tend to divide the work in ways that are hard for humans to label.

Total versus active parameters

MoE models come with two numbers:

  • Total parameters: every weight in the model, including all experts. All of these must be stored in memory.
  • Active parameters: the weights actually used to produce one token: the shared parts (attention, embeddings) plus the chosen experts.

Real examples, as published by their makers:

  • Mixtral 8x7B: about 46.7B total, about 12.9B active; 8 experts per layer, 2 chosen per token.
  • DeepSeek-V2: 236B total, 21B active.
  • gpt-oss-120b: 117B total, 5.1B active.
  • Qwen3-Next-80B-A3B: 80B total, about 3B active, with 512 experts per MoE layer, 10 chosen per token plus 1 always-on shared expert.

The "A3B" style of name, meaning "3B active", has become a common way to advertise this.

Why MoE generates faster

Writing each new token (the decode phase) is mostly limited by memory bandwidth: how many gigabytes per second the hardware can read from memory. For every token, the model must read the weights it uses. A dense model reads all of them; an MoE model reads only the active ones. Less data read per token means more tokens per second.

The catch is that you do not know in advance which experts the next token will need, so all of them must sit in fast memory, ready. MoE saves time, not space.

Worked example: 120B MoE versus 70B dense

Take a machine with 128 GB of unified memory (memory shared by the CPU and GPU, as on Apple silicon Macs and some PC chips) and 500 GB/s of memory bandwidth. Compare a 120B-total, 5B-active MoE model with a 70B dense model, both quantized to about 4.5 bits per weight. We use this site's AI Index formulas.

Step 1: usable memory. macOS lets the GPU use about 75% of unified memory by default, so 128 × 0.75 = 96 GB. A model "fits" if it needs no more than 85% of that: 81.6 GB.

Step 2: memory needed (file size ≈ parameters × bits ÷ 8, plus 5%, then KV cache and 1.5 GB overhead):

  • MoE: 120 × 4.5 ÷ 8 = 67.5 GB, plus 5% ≈ 71 GB. Add about 3 GB of KV cache for a moderate context and 1.5 GB of overhead: about 75.5 GB. It fits, just.
  • Dense: 70 × 4.5 ÷ 8 ≈ 39.4 GB, plus 5% ≈ 41 GB. Add 3 GB and 1.5 GB: about 46 GB. Fits easily.

Step 3: generation speed. The site's estimate is tok/s ≈ 1 ÷ (bytes per token ÷ (0.55 × bandwidth) + 1.5 ms), where bytes per token ≈ active parameters × bits ÷ 8, and 0.55 reflects that real hardware reaches only about half its rated bandwidth.

  • MoE: 5 × 4.5 ÷ 8 ≈ 2.8 GB per token. 2.8 ÷ 275 GB/s ≈ 10.2 ms, plus 1.5 ms ≈ 11.7 ms per token: about 85 tokens per second.
  • Dense: 39.4 GB per token. 39.4 ÷ 275 ≈ 143 ms, plus 1.5 ms ≈ 145 ms: about 7 tokens per second.
120B MoE (5B active)70B dense
Memory needed~75 GB~46 GB
Fits in 81.6 GB budget?Yes, barelyYes
Estimated speed~85 tok/s~7 tok/s

The MoE model needs more memory but writes roughly twelve times faster. Real numbers will differ (routing adds some overhead, and the KV cache depends on the architecture), but the direction holds. The same pair on a 24 GB graphics card tells the other side of the story: neither fits, and the MoE model is the bigger problem.

Trade-offs

  • Quality per total size. An MoE model generally does not match a dense model with the same total parameter count; it trades some quality per stored parameter for much cheaper computation. It often matches or beats dense models with similar active-parameter cost.
  • Prompt processing. Reading your prompt (the prefill phase) is limited mainly by compute, at about 2 × active parameters in arithmetic operations per token, so MoE helps here too.
  • Offloading. Because only a few experts run per token, some runtimes keep rarely-needed expert weights in ordinary system RAM. That works, but speed drops toward system-RAM bandwidth.
  • Serving at scale. Providers like MoE because cost per token tracks active parameters, which is part of why large hosted models are often MoE.

Going deeper

The router, formally

Let x∈Rdx \in \mathbb{R}^d be a token's hidden vector entering an MoE layer with EE experts f1,…,fEf_1, \dots, f_E (each a small feed-forward network) and a router matrix Wr∈Rd×EW_r \in \mathbb{R}^{d \times E}. The router computes one score per expert and turns them into probabilities with a softmax:

h=Wr⊤x,pi=ehi∑j=1Eehj.h = W_r^\top x, \qquad p_i = \frac{e^{h_i}}{\sum_{j=1}^{E} e^{h_j}}.

Let T\mathcal{T} be the indices of the kk largest pip_i (top-kk). The layer output is a gated sum of only those experts:

y=∑i∈Tgi fi(x),gi=pi∑j∈Tpj.y = \sum_{i \in \mathcal{T}} g_i\, f_i(x), \qquad g_i = \frac{p_i}{\sum_{j \in \mathcal{T}} p_j}.

Renormalising over the chosen experts, as Mixtral does, is the same as taking a softmax over just the top-kk logits. Some designs skip renormalisation or add a shared expert that every token uses. Because the top-kk choice is not differentiable, the task loss reaches the router only through the gate values gig_i of the chosen experts (auxiliary losses, below, add a separate signal).

Worked example. With E=4E = 4, k=2k = 2 and logits h=(2,1,0,−1)h = (2, 1, 0, -1): the softmax gives p≈(0.644,0.237,0.087,0.032)p \approx (0.644, 0.237, 0.087, 0.032). Experts 1 and 2 are chosen, and their gates are 0.644/0.881≈0.7310.644 / 0.881 \approx 0.731 and 0.237/0.881≈0.2690.237 / 0.881 \approx 0.269, equivalently 1/(1+e−1)1/(1 + e^{-1}) and 1/(1+e1)1/(1 + e^{1}).

Load balancing

Left alone, a router tends to collapse: a few experts get most tokens, train faster, get chosen even more, and the rest are wasted. The Switch Transformer paper added an auxiliary loss. For a batch of TT tokens, let fif_i be the fraction of routing assignments sent to expert ii and PiP_i the mean router probability for expert ii:

Laux=α⋅E∑i=1Efi Pi.\mathcal{L}_{\text{aux}} = \alpha \cdot E \sum_{i=1}^{E} f_i\, P_i .

fif_i is not differentiable (it counts discrete choices), but PiP_i is, so the gradient lowers the probability of overloaded experts. Under perfectly uniform routing fi=Pi=1/Ef_i = P_i = 1/E, giving E⋅E⋅(1/E2)=1E \cdot E \cdot (1/E^2) = 1, so the unscaled loss is 1 when balanced and grows with imbalance. Switch used α=10−2\alpha = 10^{-2}. Example with E=4E = 4, f=(0.4,0.3,0.2,0.1)f = (0.4, 0.3, 0.2, 0.1) and P=(0.35,0.3,0.2,0.15)P = (0.35, 0.3, 0.2, 0.15): ∑fiPi=0.14+0.09+0.04+0.015=0.285\sum f_i P_i = 0.14 + 0.09 + 0.04 + 0.015 = 0.285, so the unscaled loss is 4×0.285=1.144 \times 0.285 = 1.14.

Training systems also set an expert capacity, the most tokens an expert may take per batch: capacity=⌈CF⋅Tk/E⌉\text{capacity} = \lceil \text{CF} \cdot T k / E \rceil, where the capacity factor CF is typically a little above 1. Tokens beyond capacity are dropped from that expert and pass through the layer's residual connection unchanged. Many recent inference engines avoid dropping altogether.

Worked example: where Mixtral's 46.7B and 12.9B come from

Mixtral 8x7B uses the same layer shapes as a 7B-class Llama model: d=4096d = 4096, 32 layers, 8 KV heads of size 128, SwiGLU experts with dff=14336d_{ff} = 14336, a 32,000-token vocabulary, 8 experts and top-2 routing.

  • One expert: 3⋅4096⋅14336=176,160,7683 \cdot 4096 \cdot 14336 = 176{,}160{,}768 weights.
  • All experts: 32×8×176.16M≈45.10B32 \times 8 \times 176.16\text{M} \approx 45.10\text{B}.
  • Attention: 32×41.94M≈1.34B32 \times 41.94\text{M} \approx 1.34\text{B}; embeddings and head 2×32000×4096≈0.26B2 \times 32000 \times 4096 \approx 0.26\text{B}; routers about 1M.
  • Total ≈ 46.70B. Active: replace 8 experts with 2, so 32×2×176.16M≈11.27B32 \times 2 \times 176.16\text{M} \approx 11.27\text{B}, plus the same 1.60B of shared parts: ≈ 12.88B.

Both match the published figures, and the arithmetic shows the name "8x7B" is not 8×7=568 \times 7 = 56B: only the feed-forward blocks are replicated.

Why batching erodes the advantage

The bandwidth saving assumes one token at a time. A server decoding a batch of BB tokens at once must read every expert that any of them selects. If routing were uniform and independent, the expected number of distinct experts touched per layer is

E[experts read]=E(1−(1−kE)B).\mathbb{E}[\text{experts read}] = E\left(1 - \left(1 - \frac{k}{E}\right)^{B}\right).

For Mixtral (E=8E = 8, k=2k = 2): 2 experts at B=1B = 1, about 5.5 at B=4B = 4 and about 7.9 at B=16B = 16. By a batch of 16, nearly all expert weights are read every step, so per-step memory traffic approaches that of a dense model of the same total size; the saving that remains is in compute, which still follows the active count. That is why MoE is ideal for single-user local decoding and still cheap per token at scale, but for different reasons.

Code: a top-k router with the balancing loss

import numpy as np

rng = np.random.default_rng(0)
T, d, E, k = 1024, 64, 8, 2              # tokens, model width, experts, top-k
x = rng.standard_normal((T, d))
W_r = rng.standard_normal((d, E)) * 0.1   # router weights
W_e = rng.standard_normal((E, d, d)) / np.sqrt(d)  # toy experts: one matrix each

logits = x @ W_r                                    # (T, E)
p = np.exp(logits - logits.max(axis=1, keepdims=True))
p /= p.sum(axis=1, keepdims=True)                   # router softmax
topk = np.argsort(-p, axis=1)[:, :k]                # chosen experts per token
gates = np.take_along_axis(p, topk, axis=1)
gates /= gates.sum(axis=1, keepdims=True)           # renormalise over top-k

y = np.zeros_like(x)
for slot in range(k):                                # weighted sum of k experts
    e = topk[:, slot]
    y += gates[:, slot:slot + 1] * np.einsum("td,tdo->to", x, W_e[e])

f = np.bincount(topk.ravel(), minlength=E) / (T * k)  # share of assignments
P = p.mean(axis=0)                                     # mean router probability
aux = E * np.sum(f * P)                                # equals 1.0 when uniform
print("load per expert:", np.round(f, 3))
print("aux loss (unscaled):", round(float(aux), 4))

The loop runs each token through its chosen experts and weights the results by the renormalised gates; the last lines compute the Switch-style loss. Real implementations group tokens by expert so each expert does one large matrix multiply, and, when experts are spread over GPUs (expert parallelism), exchange tokens with an all-to-all communication step, which is often the bottleneck in serving.

Compute

Prefill and training compute follow the active count: about 2Nactive2 N_{\text{active}} FLOPs per token forward. Mixtral therefore computes like a roughly 13B dense model while storing about 47B parameters.

Common pitfalls

  • Sizing hardware from the active count. Every expert must be resident (or streamed at a heavy speed cost).
  • Reading "8x7B" as 56B. Attention and embeddings are shared; only the feed-forward blocks are copied.
  • Assuming experts are topic specialists. Routing patterns are learned and mostly not human-interpretable.
  • Ignoring batch effects. At large batch sizes, different tokens hit different experts, so a server reads most experts every step and the bandwidth advantage of sparsity shrinks.
  • Fine-tuning without balancing. Dropping the auxiliary loss (or its equivalent) during fine-tuning can collapse routing.

In practice

  • When you see an MoE model, plan memory on the total parameter count and expect speed in line with the active count.
  • MoE models suit machines with a lot of memory but modest bandwidth, such as large unified-memory computers.
  • On a small GPU, a dense model that fits entirely in video memory may beat a larger MoE that has to spill into system RAM.
  • Check the model card for both numbers; names like "A3B" or "A22B" tell you the active count.

Key takeaways

  • A mixture-of-experts model has many expert sub-networks and a router that sends each token to only a few of them.
  • Total parameters decide how much memory you need; active parameters decide how fast tokens are generated.
  • Because generation is limited by memory bandwidth, reading fewer weights per token makes MoE models much faster than dense models of similar total size.
  • All experts must still be held in memory, since any of them might be needed for the next token.
  • On a 128 GB, 500 GB/s machine, a 120B-total, 5B-active MoE can generate more than ten times faster than a 70B dense model while using more memory.

Terms in this lesson

Mixture of experts (MoE)
A model design where each layer has many expert sub-networks and only a few are used per token.
Expert
One of the smaller feed-forward sub-networks inside an MoE layer.
Router (gate)
A small network that scores the experts and picks which ones process each token.
Total parameters
Every weight in the model, all of which must be stored in memory.
Active parameters
The weights actually used to produce a single token.
Memory bandwidth
How many gigabytes per second the hardware can read from memory, the main limit on generation speed.
Unified memory
A single pool of memory shared by the CPU and GPU on the same chip package.
Top-k routing
Sending each token only to the k experts with the highest router scores and weighting their outputs by renormalised gate values.
Load-balancing loss
An auxiliary training loss that penalises uneven routing so that tokens spread across experts.
Expert capacity
The maximum number of tokens one expert may process per batch, set by a capacity factor; overflow tokens skip the expert.

Check your understanding

  1. 1.

    Why must an MoE model keep all of its experts in memory even though only a few run per token?

  2. 2.

    Two models are quantized the same way: a 100B-total, 10B-active MoE and a 30B dense model. On the same hardware, which will most likely generate tokens faster?

  3. 3.

    You have a single 24 GB graphics card. Which statement is most accurate?

  4. 4.

    An MoE layer has 4 experts and top-2 routing. The router logits for a token are (2, 1, 0, -1). What gate weight does the top expert get after renormalising over the chosen two?

  5. 5.

    In the Switch-style auxiliary loss α · E · Σ f_i P_i, what value does the unscaled sum E · Σ f_i P_i take when routing is perfectly uniform?

Exercises

Work each problem before opening the solution.

  1. Exercise 1Core

    A hypothetical MoE model has d=2048d = 2048, 24 layers, 16 query heads and 4 KV heads of size 128, SwiGLU experts with dff=8192d_{ff} = 8192, 16 experts per layer with top-2 routing, a router per layer, two RMSNorms per layer, and a 50,000-token vocabulary with untied embeddings. Compute total and active parameters.

    Show solution

    Per layer:

    • One expert: 3⋅2048⋅8192=50,331,6483 \cdot 2048 \cdot 8192 = 50{,}331{,}648.
    • Attention: 2⋅2048⋅2048+2⋅2048⋅4⋅128=8,388,608+2,097,152=10,485,7602 \cdot 2048 \cdot 2048 + 2 \cdot 2048 \cdot 4 \cdot 128 = 8{,}388{,}608 + 2{,}097{,}152 = 10{,}485{,}760.
    • Router: 2048⋅16=32,7682048 \cdot 16 = 32{,}768; norms: 4,096.

    Total per layer: 16×50,331,648+10,485,760+32,768+4,096=815,828,99216 \times 50{,}331{,}648 + 10{,}485{,}760 + 32{,}768 + 4{,}096 = 815{,}828{,}992; times 24 = 19,579,895,808. Add embeddings and head 2×50000×2048=204,800,0002 \times 50000 \times 2048 = 204{,}800{,}000 and the final norm 2,048: total ≈ 19.78B.

    Active per layer: 2×50,331,648+10,485,760+32,768+4,096=111,185,9202 \times 50{,}331{,}648 + 10{,}485{,}760 + 32{,}768 + 4{,}096 = 111{,}185{,}920; times 24 = 2,668,462,080; plus 204,802,048 = active ≈ 2.87B (about 14.5% of the total).

  2. Exercise 2Core

    A router over 4 experts produces assignment fractions f=(0.4,0.3,0.2,0.1)f = (0.4, 0.3, 0.2, 0.1) and mean probabilities P=(0.35,0.3,0.2,0.15)P = (0.35, 0.3, 0.2, 0.15) on a batch. Compute the auxiliary loss with α=0.01\alpha = 0.01 and compare it with the balanced value.

    Show solution

    ∑fiPi=0.4(0.35)+0.3(0.3)+0.2(0.2)+0.1(0.15)=0.14+0.09+0.04+0.015=0.285\sum f_i P_i = 0.4(0.35) + 0.3(0.3) + 0.2(0.2) + 0.1(0.15) = 0.14 + 0.09 + 0.04 + 0.015 = 0.285. Unscaled: 4×0.285=1.144 \times 0.285 = 1.14; with α=0.01\alpha = 0.01 the loss is 0.0114. A balanced router gives 0.01×1=0.010.01 \times 1 = 0.01, so this batch is mildly imbalanced and the gradient will lower P1P_1 (the overloaded expert's probability).

  3. Exercise 3Core

    Write a function that, given the (T, k) array of chosen expert ids from the lesson's router and a capacity factor, returns each expert's capacity, its load and the number of assignments that overflow. Compare uniform routing with a skewed router.

    Show solution
    import numpy as np
    
    def dropped_tokens(topk, n_experts, capacity_factor=1.25):
        T, k = topk.shape
        capacity = int(np.ceil(capacity_factor * T * k / n_experts))
        load = np.bincount(topk.ravel(), minlength=n_experts)
        overflow = np.maximum(load - capacity, 0)
        return capacity, load, int(overflow.sum())
    
    rng = np.random.default_rng(0)
    balanced = rng.integers(0, 8, size=(1024, 2))
    skewed = rng.choice(8, size=(1024, 2), p=[.3, .2, .1, .1, .1, .1, .05, .05])
    for name, t in (("balanced", balanced), ("skewed", skewed)):
        print(name, *dropped_tokens(t, 8))
    

    With 1,024 tokens, top-2 and 8 experts, capacity is ⌈1.25×2048/8⌉=320\lceil 1.25 \times 2048 / 8 \rceil = 320. Uniform routing stays under capacity (loads around 230 to 270, nothing dropped); the skewed router sends about 630 and 450 assignments to the two favourite experts, so several hundred (437 with this seed) overflow. That waste is exactly what the balancing loss is meant to prevent. (For simplicity this counts overflow per expert rather than deciding which specific tokens are dropped.)

  4. Exercise 4Challenge

    A machine has 192 GB of unified memory (macOS default GPU limit about 75%) and 800 GB/s of bandwidth. You want a 235B-total, 22B-active MoE model. (a) At 4.5 bits per weight with a 4 GB KV cache, does it fit by this site's rule? (b) What decode speed would the site's formula predict if it did fit? (c) What is the highest average bits per weight that fits?

    Show solution

    (a) Usable: 192×0.75=144192 \times 0.75 = 144 GB; fit threshold 0.85×144=122.40.85 \times 144 = 122.4 GB. File: 235×4.5/8=132.2235 \times 4.5 / 8 = 132.2 GB, plus 5% = 138.8 GB; total 138.8+4+1.5=144.3138.8 + 4 + 1.5 = 144.3 GB. Does not fit.

    (b) Bytes per token: 22×4.5/8=12.37522 \times 4.5 / 8 = 12.375 GB. Effective bandwidth 0.55×800=4400.55 \times 800 = 440 GB/s. Time: 12.375/440=28.112.375 / 440 = 28.1 ms, plus 1.5 ms = 29.6 ms, about 34 tokens/s.

    (c) Need 1.05×235×b/8+5.5≤122.41.05 \times 235 \times b / 8 + 5.5 \le 122.4, so b≤(116.9/1.05)×8/235≈3.79b \le (116.9 / 1.05) \times 8 / 235 \approx 3.79 bits. A roughly 3.5-bit quant (an IQ3-class GGUF, for example) would fit, at some quality cost that you should test; speed would rise slightly because fewer bytes are read per token.

Further reading

Go further

Sources

Fact-checked and last reviewed 2026-11-05

Stay in the loop
Prometheus OS™ · Native AI OS · Built for the future © 2025 - 2026