Compute-Optimal Training › Optimal Allocation Formulas
Language AI HandbookAll chapters Compute-Optimal Training › Optimal Allocation FormulasOne section · Sections in this chapter3 / 11 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Let's derive the formulas for compute-optimal training from first principles. This derivation illuminates the mathematical machinery behind the Chinchilla recommendations and provides insight into why the specific ratios emerge. Building on the Chinchilla loss function:
where:
- : the expected loss as a function of model size and data
- : the irreducible entropy of natural language (the theoretical minimum loss)
- : empirically fitted coefficients that determine the relative importance of model size vs. data
- : model parameters raised to power , capturing how loss decreases with model size
- : training tokens raised to power , capturing how loss decreases with more data
This functional form reveals important structure in language model training. The loss decomposes into three distinct components, each with a clear interpretation. The constant term represents the irreducible entropy of natural language, the inherent unpredictability that no model, however large or well-trained, can overcome. Human language has inherent randomness: there are many ways to phrase the same idea, and even expert human predictions of the next word would not achieve zero error. The second term captures how loss decreases as you add model capacity. The power law form means that doubling your parameters doesn't halve this component of loss; rather, it reduces it by a factor of . The diminishing returns are already built into this formulation. Similarly, the third term captures how loss decreases with more training data, again with diminishing returns governed by the exponent .
The functional form reveals that loss decreases as power laws in both and , but with different exponents, meaning model size and data have different marginal returns. To find the optimal allocation given a fixed compute budget , we minimize loss subject to this constraint.
Using the method of Lagrange multipliers (or substitution), the optimal allocation satisfies:
where all variables are as defined above for the loss function. This implicit equation emerges from setting the partial derivatives of the Lagrangian to zero. The left side represents the ratio of parameters to tokens we seek to determine. The right side involves the empirical constants from the loss function, weighted by the ratio of exponents. The self-referential nature of this equation, where the ratio appears on both sides, reflects the coupled nature of the optimization problem. It can be solved by substituting the empirically fitted values (, , and the ratio ). After simplification, this yields a tokens-to-parameters ratio that Chinchilla estimated empirically:
This ratio tells us that for every parameter in your model, you should train on approximately 20 tokens. A 1B parameter model should see about 20B tokens, and a 70B model should see about 1.4T tokens.
This result is notable for its simplicity. Despite the complexity of the optimization problem and the many factors that could influence training, the optimal ratio distills to a single number that holds across orders of magnitude in compute scale. This ratio is remarkably stable across compute scales. Whether you're training a 1B or 100B parameter model, compute-optimal training uses approximately 20 tokens per parameter.
To develop intuition for why 20 tokens per parameter is the magic number, consider what happens at the extremes. If you train with far fewer tokens per parameter (say 2), your model has enormous capacity relative to the training signal it receives. Many parameters will be undertrained, effectively storing noise rather than useful patterns. The model might memorize training examples rather than learning generalizable features. Conversely, if you train with far more tokens per parameter (say 200), you're repeatedly refining a model that has already extracted most of what it can from the data given its limited capacity. The marginal improvement from each additional token becomes negligible. The ratio of 20 represents the sweet spot where both forms of inefficiency are minimized.
Practical Formulas
Given a compute budget (in FLOPs), the compute-optimal model size and token count are:
These formulas follow from combining with . Substituting the second into the first gives , which we solve for . This algebra turns the abstract scaling principles into concrete, calculator-ready equations. The factor of 120 in the denominator encapsulates both the computational cost structure (the 6) and the optimal data ratio (the 20), bundling all the Chinchilla insights into a single coefficient.
For back-of-the-envelope calculations, these can be approximated as:
where:
- : the optimal number of model parameters
- : the optimal number of training tokens
- : total compute budget in FLOPs
- : derived from solving for
- : the token coefficient, since
These numerical coefficients make the formulas immediately usable. Given any compute budget expressed in FLOPs, you can quickly estimate the optimal allocation by taking the square root and scaling. The coefficient 0.091 for parameters is conveniently close to 0.1, making mental math tractable: a budget of FLOPs suggests optimal parameters around , or roughly 10 billion parameters.
Let's implement these formulas:
import math
def compute_optimal_allocation(compute_flops: float) -> dict:
"""
Calculate optimal model size and token count for a given compute budget.
Args:
compute_flops: Total compute budget in FLOPs
Returns:
Dictionary with optimal N (parameters) and D (tokens)
"""
# Chinchilla's empirical ratio: ~20 tokens per parameter
tokens_per_param = 20
# From C = 6ND and D = 20N:
# C = 6 * N * 20 * N = 120 * N^2
# N = sqrt(C / 120)
n_opt = math.sqrt(compute_flops / (6 * tokens_per_param))
d_opt = tokens_per_param * n_opt
return {
"params": n_opt,
"tokens": d_opt,
"compute": compute_flops,
"tokens_per_param": d_opt / n_opt,
}
# Example: Compute budget equivalent to training GPT-3
# GPT-3: 175B params, ~300B tokens → C ≈ 6 * 175e9 * 300e9 = 3.15e23 FLOPs
gpt3_compute = 3.15e23
optimal = compute_optimal_allocation(gpt3_compute)
# Verify the calculation
assert optimal["tokens_per_param"] == 20.0, "Token ratio should be 20"GPT-3's actual compute budget: 3.15e+23 FLOPs Compute-optimal allocation: Model size: 51.2B parameters Training tokens: 1.02T tokens Tokens per parameter: 20.0 GPT-3's actual allocation: Model size: 175B parameters Training tokens: 0.30T tokens Tokens per parameter: 1.7

This calculation reveals that GPT-3 was significantly undertrained by Chinchilla standards. The comparison is striking: GPT-3 used only 1.7 tokens per parameter, roughly ten times less than the Chinchilla-optimal 20. This means the vast majority of GPT-3's 175 billion parameters were receiving insufficient training signal, they contributed to computational cost without being properly configured by data. The same compute budget would have produced a better model with around 51B parameters trained on over 1T tokens. This is essentially what Chinchilla demonstrated: their 70B model (trained on 1.4T tokens) outperformed the 280B Gopher despite using comparable compute.