skip to content

Why can a global gradient norm in 16-bit come out infinite when every gradient is finite?

level: seniorimportance: nice to knowfreq 31%

answer

  1. look at the sum, not the elements
  2. element count drives the magnitude
  3. 65504 is a low ceiling for a total
  4. the opposite failure is a silent stall
  5. accumulate wider, or rescale first

basics

~20 s

A global norm sums squares across every parameter. Each square is finite, but the running total crosses the 16-bit ceiling of 65504 and saturates to infinity. The failure lives in the accumulator, not in any individual gradient.

solid answer

~40 s

The norm is `sqrt(sum of g_i^2)` over every element in the model. A 16-bit float's 5 exponent bits cap the largest finite value at `65504`, so with 100,000 elements whose squares average even 0.7 the partial sum crosses that ceiling partway through and becomes `inf` — and `sqrt(inf)` is `inf`, while every gradient inspected on its own looks ordinary. The same accumulator fails at the other end too: once the running total reaches 2000, one ulp there is about 2, so squares of 1e-4 add nothing and the sum silently stalls at an underestimate. Both are properties of the reduction, not of the data. Fix it by accumulating in a wider format, or by dividing by the largest element magnitude before squaring and multiplying the scale back after the square root.

go deeper

for a junior

Recall that a sum over many values can be far larger than any single value, and that every format has a largest finite number it can hold. Know that exceeding it gives infinity rather than an error.

for a middle

Explain why a reduction is the exposed operation: the output magnitude scales with the element count, the 16-bit ceiling is 65504, and spacing in the partial sum grows as the total grows so small addends stop contributing. Be able to do the mean-square-under-65504-over-n arithmetic.

for a senior

Show the diagnostic discipline: before blaming an exploding gradient, check the maximum element magnitude against the total, and check whether the same reduction in wider precision is finite. Be ready to propose wider accumulation, rescaling by the maximum, or a tree reduction, and to say what each costs.

for a principal

Own the general rule that accumulation precision is a separate decision from storage precision, and decide where in a training and evaluation stack reductions must be widened by default. Be ready to argue for numerical checks on aggregate statistics rather than trusting that finite inputs imply finite outputs.

## Reductions are where formats break first Elementwise arithmetic keeps values in the same neighbourhood: multiply two order-1 numbers and you get an order-1 number. A **reduction** — a sum over many elements — does not. Its output magnitude grows with the number of elements, and a training run reduces over tensors with millions of them. So the format constraint that matters is not "can this format hold a gradient" but "can this format hold a sum of a hundred thousand of them". A global gradient norm is the canonical case: `sqrt(sum over all parameters of g_i^2)`. ## The overflow arithmetic A 16-bit float has 5 exponent bits, and its largest finite value is `65504`. Suppose 100,000 elements with gradients of magnitude around 1. Each square is around 1 and entirely unremarkable. The running sum passes `65504` after roughly 65,000 of them and becomes `inf`. The remaining additions leave it there, `sqrt` of it is `inf`, and anything computed from the norm inherits the infinity. The diagnostic trap is that this looks exactly like an exploding gradient. Every instinct says to hunt for the one huge value. There is no huge value: the maximum element is 1. What overflowed is the accumulator, and the two situations demand opposite responses — one is a modelling or stability problem, the other is a numerics bug in a reduction that would have been fine at any element magnitude if the element count were smaller. A useful reflex: for a sum of `n` squares to stay under `65504`, the mean square must be under `65504/n`. At `n = 100,000` that is a mean gradient magnitude of about `0.8`. That is not an exotic condition — it is an ordinary one. ## The mirror failure: a sum that stalls The same accumulator fails in the opposite direction without ever producing an infinity. Precision in floating point is relative, so the spacing between representable values grows with the running total. Once a 16-bit sum has reached about 2000, one ulp is about 2; any addend below about 1 is invisible. If you are summing a long tail of small squares — say `1e-4` each — after the total has grown large, every one of them rounds away and contributes exactly nothing. The result is a norm that is finite, plausible-looking, and systematically too small. That is arguably more dangerous than the infinity, because an infinity announces itself and a quiet underestimate does not: anything that consumes the norm as a threshold or a scale then behaves as though the gradients were smaller than they are. Ordering matters here in a way it does not for overflow. Summing smallest-first lets small values combine with each other before meeting the large partial sum, which recovers some of the lost mass — but it is a mitigation, not a fix, and it does nothing about the ceiling. ## Machine epsilon as a budget A compact way to reason about drift: each rounded addition costs at most one unit roundoff of relative error — `2^-11` ≈ `4.9e-4` for 16-bit, `2^-24` ≈ `6e-8` for 32-bit. Chain `n` sequential additions and worst-case relative error grows on the order of `n` times that (random-walk cancellation usually makes it closer to `sqrt(n)` times in practice). A 16-bit running statistic accumulated over a few thousand sequential steps — a moving average over a long time series, for instance — has therefore burned its entire relative-precision budget, while the same chain in 32-bit is still five orders of magnitude away from mattering. It is the same budget question as the norm, spread over time instead of over elements. ## Fixes **Accumulate wider than you store.** The elements can live in a narrow format; the running total should not. This is a standard hardware design point rather than an exotic trick: matrix units multiply narrow inputs and accumulate the products in a wider format precisely because the reduction, not the multiply, is what loses information. **Rescale before squaring.** Compute `M = max |g_i|`, then `M * sqrt(sum (g_i / M)^2)`. Every squared term is now at most 1, the sum is at most `n`, and the ceiling is only reached if the element count itself is enormous. This is the classical scaled-hypotenuse trick and it costs one extra pass over the data. **Tree or blocked reduction.** Summing in pairs or in per-block partials keeps the partial sums closer in magnitude to the elements, which reduces both overflow exposure and drift — and it is what parallel hardware does naturally anyway, since a parallel reduction is a tree. ## What to take away The question "is this value representable?" is the wrong one for a reduction. The right question is "is every intermediate value in this reduction representable, and does each addend survive being added to the partial sum it meets?" Overflow and drift are the two ways the answer is no, and both are fixed at the accumulator, not at the data.

  • What is the mirror failure of the same accumulator, and why is it more dangerous?
    Drift. Once the running total is large, one ulp there exceeds the small squares still being added, so they round away and contribute nothing. The norm comes out finite and plausible but systematically too small. An infinity announces itself immediately; a quiet underestimate propagates into whatever consumes the norm as a scale or a threshold.
  • Why does the element count matter as much as the gradient magnitudes?
    Because a sum grows roughly linearly with the number of terms. For 100,000 squares to stay under 65504, the mean square must be below about 0.65 — a mean magnitude around 0.8. Real models reduce over far more elements than that, so the reduction crosses the ceiling at completely ordinary per-element magnitudes.
  • How would you make the norm safe without changing how gradients are stored?
    Accumulate the running total in a wider format, which is the cheapest and most robust option, or rescale: take M as the maximum absolute gradient, sum the squares of g_i divided by M, then multiply the square root back by M. Every squared term is then at most 1, so the partial sum cannot approach the ceiling.

saying these in an interview costs you the question

  • Hunts for one exploding element without checking the reduction
  • Assumes finite inputs guarantee a finite sum
  • Thinks an infinity can only come from division by zero
  • Believes reductions always run in the storage precision
  • Ignores the silent underestimate because nothing crashed

context