How frontier models store hundreds of billions of parameters and use a few billion per token, from the router's gradient to the all-to-all traffic, the balancing tricks, and the designs behind Mixtral and DeepSeek-V3.
Conditional computation
Here is a puzzle about the model you built in Chapter 6. When it reads the token "the", every one of its parameters takes part. The weights that, in a trained model, store facts about protein folding, Python syntax, and the kings of France are all multiplied through, and almost all of that work is wasted on a token that needs none of it. Now suppose you want a model that knows eight times as much. A dense Transformer gives you exactly one way to get it, eight times the parameters, and with them eight times the arithmetic for every token, forever, in training and in serving.
Is there a way to have the parameters without paying for them on every token? That question is conditional computation, and the answer that took over frontier language models is the mixture of experts (MoE). Mixtral 8x7B stores 46.7 billion parameters and uses 12.9 billion of them per token. DeepSeek-V3 stores 671 billion and uses about 37 billion. By the end of this section you will be able to derive both pairs of numbers on a whiteboard, say exactly what an MoE layer computes, explain why it is not an ensemble, and trace the idea from a 1991 paper on vowel recognition to today's largest open models.
Parameters and FLOPs are welded together in a dense model
Recall the 6N rule from §5.6. Every weight in a matrix multiplication does one multiply and one add per token in the forward pass, so a model with such weights costs about FLOPs per token forward and to train, and for training tokens. The rule has no slack in it. Each parameter is touched by each token, so parameters and compute are welded together.
That would not matter if parameters were cheap in some other way, but they are what a model knows. In §5.3 we read the feed-forward network as a key-value memory, with each hidden unit a key that fires on some pattern and writes a value back into the stream, and the FFNs hold about two thirds of each block's weights. Scaling laws (§9.2) say loss keeps falling as parameters grow. So we want more of them, and the dense recipe charges us for every one of them on every token.
Conditional computation breaks the weld. Keep many FFNs, and let each token use only a few of them, chosen by a small learned function of the token itself. The parameter count, and with it the capacity to store knowledge, grows with the number of FFNs. The compute per token grows only with the number used.
The MoE layer
An MoE layer replaces the FFN sublayer of a Transformer block. Attention, the norms, and the residual stream stay exactly as they were. For one token's input (a row, the output of the pre-FFN norm), the layer has
- experts, each an ordinary FFN of the kind in §5.3. In modern models each is a SwiGLU network with and , where is the expert's hidden width.
- a router (also called the gate), a linear map that gives one logit per expert, .
- a number of experts to use per token, usually 1, 2, or 8.
The router picks the experts with the largest logits, the set , turns their logits into weights that sum to one, and the layer returns the weighted sum of just those experts' outputs,
In plain words, score every expert with one cheap matrix product, keep the best , run only those, and blend their answers in proportion to how strongly the router preferred them.
The block is otherwise unchanged, . Two details matter from the start. The experts that are not chosen are never evaluated, which is the whole point. And the router itself is evaluated for all experts, which costs FLOPs per token, tiny next to an expert (about ) but not zero. There are several ways to turn router logits into weights (softmax over all experts, softmax over the chosen ones, sigmoids), and they behave differently in training. §13.2 takes them apart. Here we use the version above, which is Mixtral's.
A worked example small enough to check by hand
Take , , , and a router whose logits for one token come out as . The top two are experts 0 and 2. Their weights are a two-way softmax,
and . The layer runs experts 0 and 2 and returns . The cell below does exactly this, then checks it against the wasteful version that runs all four experts and multiplies the unused ones by zero.
Total and active parameters
Two counts describe an MoE model, and confusing them is the most common mistake people make about these models.
- The total parameters are everything stored. They set the memory needed to hold the model.
- The active parameters are the ones a single token actually multiplies through. They set the FLOPs per token, so they play the role of in the 6N rule.
For one MoE layer with SwiGLU experts of width , a bias-free router, and experts per token,
In plain words, storage grows with the number of experts, compute grows with the number used, and the router is the only part every token pays for in full.
Mixtral 8x7B, counted exactly
Mixtral (Jiang et al. 2024) is Mistral 7B with each FFN replaced by eight copies of the same shape and top-2 routing. Its published configuration is , layers, query heads and key-value heads of width , , , , a vocabulary of , and separate (untied) input and output embeddings. Count one layer.
- Attention with grouped-query attention (§4.5). and are (since ), and , are (since ), so .
- One expert. Three matrices of , so . Eight of them are .
- Router. .
- Two RMSNorm gains. .
That is per layer and for 32 layers. Add the input and output embeddings, , and the final norm's , and the total is
For the active count, replace eight experts by two in every layer, , which gives per layer and
counting both embedding matrices in full. (Leave out the input embedding, which is a lookup and costs no FLOPs, and it is 12.7B. Both round to the paper's "13B active".)
Why is "8x7B" not 56 billion? Because only the FFNs were multiplied by eight. Mistral 7B has 7.24B parameters, of which 1.60B are attention, norms, and embeddings, and those are shared by all experts. Eight copies of the 5.64B of FFN weights plus one copy of the shared 1.60B is 46.7B.
DeepSeek-V3, counted exactly
DeepSeek-V3 (DeepSeek-AI 2024) has and layers. The first three layers keep a dense SwiGLU FFN of width 18,432. The other 58 are MoE layers with routed experts of width , of them per token, plus one shared expert of the same width that every token always uses (§13.5 explains why). Attention is multi-head latent attention (§12.5), whose projections, low-rank factors, and two small norms add up to per layer with heads. (That is a query down-projection, a query up-projection, since each head's query has 128 content and 64 rotary dimensions, a key-value down-projection that includes the shared rotary key, a up-projection to the keys and values, a output projection , and norms of sizes 1,536 and 512.) The vocabulary is , untied.
- One expert. .
- An MoE layer. Attention , plus experts , plus the router , plus two norms , is .
- A dense layer. Attention plus plus norms, .
So , the paper's 671B. Over 97% of it is routed experts. Per token, an MoE layer uses attention, the router, the norms, and nine experts (eight routed and the shared one), parameters, so
or 36.6B without the input embedding, the paper's "37B activated". (The released checkpoint also contains a multi-token prediction module used in training, which the 671B leaves out.)
Total and active parameters of an MoE model
Implement moe_param_count(cfg) returning the pair (total, active) for a decoder whose config is a dict with keys V (vocabulary), d (width), L (layers), attn (attention parameters per layer, given), n_dense (how many of the first layers keep a dense FFN), d_ff (that dense FFN's hidden width), E (routed experts per MoE layer), E_shared (shared experts, always active), k (routed experts per token), d_e (expert hidden width), and tied (whether input and output embeddings are one matrix). Every FFN and expert is a bias-free SwiGLU, every layer has two RMSNorm gains of size , there is one final norm, and the router is a bias-free matrix. Count the embedding matrices in full in both numbers.
Interviewers ask this as "how many parameters does Mixtral have, and how many does a token use?", and the tests check exactly that, plus DeepSeek-V3.
FLOPs per token, and the 6N rule for MoE
Because the unchosen experts never run, the 6N rule carries over with replaced by the active matrix parameters. Training on tokens costs
In plain words, an MoE model trains at the price of a dense model the size of its active parameters, while storing many times more.
DeepSeek-V3 was pretrained on 14.8 trillion tokens. With that is FLOPs. A dense model with all 671B parameters would have needed , eighteen times more. The paper reports 2.788 million H800 GPU hours for the whole run, 2.664 million of them for pretraining, which §8.9 turns into a model FLOPs utilization (the measure of §6.7) of about 35 percent of the BF16 peak.
Two caveats keep this honest. First, the router's FLOPs per token are real but small. For DeepSeek-V3 they are million per layer against about 793 million for the nine experts, half a percent. Second, FLOPs are not time. An MoE layer has to move tokens to their experts, often across GPUs, and run many small matrix products instead of one big one. Those costs are the subject of §13.4, and they are why an MoE model with the FLOPs of a 37B dense model does not train quite as fast as one.
Training compute of a dense model and its MoE counterpart
Implement train_flops(n_active, tokens) returning as a float, and flops_ratio(n_total, n_active) returning how many times more compute a dense model with parameters would need for the same tokens.
An MoE layer is a wide FFN with blocks switched off
It is tempting to picture an MoE model as eight small models voting. That picture is wrong in a way that matters, and the right picture comes straight from §5.3.
An FFN is a sum over its hidden units. For a ReLU network, , one key-value memory per unit. Cut the hidden units into consecutive blocks of , and the sum splits into smaller FFNs,
where uses only block 's columns of and rows of . The same holds for SwiGLU, block by block. So an MoE layer is a single FFN of width in which, for each token, all but blocks of hidden units are switched off and the surviving blocks are rescaled by their gates. In plain words, the experts are slices of one very wide memory, and the router decides which slices each token may read.
This explains three things. It is why the experts share everything else (attention, embeddings, the residual stream). It is why routing happens independently in every layer, with no notion of "the model's expert 3". A token in Mixtral picks one of expert pairs in each of 32 layers, so there are different paths through the network, which is nothing like an ensemble of eight models. And it is why an MoE model can be built from a dense one by copying its FFN into every expert (upcycling, §13.5), since that is a wide FFN with redundant blocks.
Cut a wide FFN into experts
Implement split_into_experts(W1, W2, E) that takes a ReLU FFN with and and returns a list of pairs (A_i, B_i) with A_i of shape (d, d_ff // E) and B_i of shape (d_ff // E, d), so that summing relu(X @ A_i) @ B_i over all experts reproduces the wide FFN. Expert owns hidden units to . Raise ValueError if does not divide .
Where the idea came from
The 1991 paper contains an insight that every later MoE inherits, so it is worth one derivation. Suppose expert outputs for a training case with target , and the gate gives it weight . The obvious loss blends the experts and compares the blend with the target, . Jacobs et al. point out that this makes the experts cooperate. Each expert's gradient depends on the residual left by all the others, so every expert tries to fix everyone's errors, and many experts end up used for every case.
Their fix is to make the experts compete. Treat the gate as choosing one expert at random with probability , and treat each expert's output as the mean of a unit Gaussian over targets. The loss is the negative log-likelihood of the target under that mixture,
Differentiate with respect to one expert's output. Only the -th term depends on , and , so
In plain words, each expert is pulled toward the target, weighted by , the posterior probability that it was the expert responsible. The expert that already fits best gets the largest share of the update, so experts specialize. Compare the intermediate loss , whose gradient is . When the gate starts uniform and every expert's error exceeds 1, the paper notes, that version adapts the best-fitting expert the slowest (its error is smallest), and the mixture likelihood adapts it the fastest. The cell shows it.
The best-fitting expert gets the smallest update under the first loss and nearly all of it under the second. Modern Transformer MoEs do not use this exact loss (they backpropagate the language-modeling loss through a weighted sum, closer to the cooperative form), and one consequence is that they need explicit help to keep experts from all doing the same thing or one expert doing everything. That help is §13.3.
Responsibilities in a mixture of experts
Implement responsibilities(target, O, p) for a target of shape (m,), expert outputs O of shape (E, m), and gate probabilities p of shape (E,). Return the pair (h, grad) where h of shape (E,) holds the posterior responsibilities above and grad of shape (E, m) is for . It must stay finite when every expert is far from the target (squared errors in the thousands).
In PyTorch
A readable MoE layer in PyTorch loops over experts, not tokens. For each expert it finds the tokens that chose it, runs them as one batch, and adds the weighted result back with index_add_. This is the shape of the reference Mixtral implementation in Hugging Face Transformers. §13.2 replaces the loop's bookkeeping with a sort, and §13.4 replaces the loop itself with a grouped matrix multiply.
Building the full-size layer on the meta device creates tensors with shapes but no storage, so you can count a 1.4-billion-parameter layer on a laptop. The count, , is the experts plus the router of the hand count above.
| dense FFN, width | MoE, experts of width , top- | |
|---|---|---|
| parameters stored | ||
| parameters used per token | ||
| forward FLOPs per token | ||
| memory to serve | small | large, all experts must be resident somewhere |
| extra machinery | none | router, load balancing, token dispatch |
Read more
- Jacobs, Jordan, Nowlan & Hinton (1991). Adaptive Mixtures of Local Experts. Five pages, and the cooperative versus competitive loss argument is still the clearest statement of why experts specialize.
- Shazeer et al. (2017). Outrageously Large Neural Networks: The Sparsely-Gated Mixture-of-Experts Layer. Noisy top-k gating, balancing losses, the shrinking batch problem, and the first MoE at a hundred billion parameters.
- Fedus, Zoph & Shazeer (2022). Switch Transformers: Scaling to Trillion Parameter Models with Simple and Efficient Sparsity. Top-1 routing in Transformers, and a careful account of the speed and quality trade-offs.
- Jiang et al. (2024). Mixtral of Experts. A short paper with the full configuration used for the count in this section.
- DeepSeek-AI (2024). DeepSeek-V3 Technical Report. The architecture, the 671B and 37B counts, and the training cost.
- Fedus, Dean & Zoph (2022). A Review of Sparse Expert Models in Deep Learning. A survey of the whole field by people who built much of it.