Numerical accuracy#
This document summarizes the accuracy of JAX mathematical functions.
Methodology and terminology#
Units in the Last Place (ULPs): Error is measured in ULPs relative to a higher-precision reference: for sub-64-bit types (
bfloat16,float16, andfloat32), reference values are evaluated in double precision (float64); forfloat64, reference values are evaluated usingmpmathwith 100-bit precision. For a target format with \(p\) significand bits and normal exponent range \([e_{\min}, e_{\max}]\), \(\operatorname{ulp}(r) = 2^{\min(\max(\lfloor \log_2 |r| \rfloor, e_{\min}), e_{\max}) - (p - 1)}\). A bound of \(0.5\) ULP is a correctly rounded result.Overflow and Infinity: Reference values at or beyond the round-to-nearest-even overflow threshold \(2^{e_{\max} + 1} - \frac{1}{2}\operatorname{ulp}(\text{max\_float})\) are treated as overflowing to \(\pm\infty\), so a computed \(\pm\infty\) has \(0\) ULP error. When the reference value is finite in or above the top normal binade (\(|r| \ge 2^{e_{\max}}\)) and the computed result has the same sign, rounding across the overflow threshold (either a computed \(\pm\infty\) just below the threshold, or a finite result such as \(\pm\text{max\_float}\) at or above the threshold) is measured continuously by placing \(\pm\infty\) at \(\pm 2^{e_{\max} + 1} = \pm(\text{max\_float} + 1\text{ ULP})\).
Exhaustive vs. Sampled Testing:
For 16-bit types (
bfloat16,float16) and unary operations on 32-bit types (float32), bounds are verified by exhaustive testing across all bit patterns (up to \(2^{32}\) inputs).For binary operations on
float32and all operations onfloat64, bounds are estimated by testing a sample of inputs: values at and near special points (such as 0, \(\pm 1\), \(\pm\infty\), subnormal/normal boundaries, poles, and approximation thresholds) along with random floating-point values drawn across all exponents. Because sampling cannot guarantee hitting the worst-case input, these values are empirical bounds on the maximum error.
Flush-To-Zero (FTZ) and Subnormals: Subnormal floating-point inputs and outputs (\(|v| < 2^{e_{\min}}\)) are typically flushed to zero by default, though some operations on types smaller than
float32(andfloat64on GPU) preserve gradual underflow.When gradual underflow is preserved (
ftz=False), subnormal values are measured on the standard number line against the subnormal quantum \(\operatorname{ulp}_{\text{tiny}} = 2^{e_{\min} - (p - 1)}\).When outputs flush to zero (
ftz=True), any pair of values with both \(|c| < 2^{e_{\min}}\) and \(|r| < 2^{e_{\min}}\) has \(0\) ULP error, and distances that cross the subnormal region contract the unrepresentable interval \([-(2^{e_{\min}} - \operatorname{ulp}_{\text{tiny}}), +(2^{e_{\min}} - \operatorname{ulp}_{\text{tiny}})]\) to \(0\) so that the adjacent FTZ-representable values \((-2^{e_{\min}}, 0.0, +2^{e_{\min}})\) are spaced \(1\) ULP apart rather than incurring an artificial \((2^{p-1} - 1)\)-ULP gap.
Hardware Platforms:
CPU: x86_64.
NVIDIA GPU: H100 and B200.
TPU: TPU v2–v5e, TPU v5p, TPU v6e, and TPU 7x.
bfloat16 accuracy#
Maximum error in units in the last place (ULPs) for bfloat16:
Function |
CPU |
NVIDIA GPU |
TPU v2–v5e |
TPU v5p |
TPU v6e |
TPU 7x |
|---|---|---|---|---|---|---|
1.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
2.0 |
0.5 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
1.5 |
0.5 |
1.0 |
1.0 |
1.0 |
1.0 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.5 |
0.5 |
1.0 |
0.5 |
0.5 |
0.5 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
0.5 |
0.5 |
0.5 |
1.0 |
1.0 |
1.0 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
0.5 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
|
0.5 |
1.0 |
1.0 |
1.0 |
0.5 |
0.5 |
101.0 |
101.0 |
44.0 |
44.0 |
44.0 |
75.0 |
|
0.5 |
0.5 |
1.0 |
1.0 |
0.5 |
0.5 |
|
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
1.0 |
0.5 |
0.5 |
0.5 |
|
0.5 |
0.5 |
1.0 |
0.5 |
0.5 |
0.5 |
|
2.0 |
2.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
2.5 |
2.5 |
1.0 |
1.0 |
0.5 |
63.0 |
|
0.5 |
0.5 |
1.0 |
1.0 |
0.5 |
0.5 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
0.5 |
0.5 |
1.0 |
1.0 |
1.0 |
1.0 |
|
0.5 |
0.5 |
1.0 |
1.0 |
1.0 |
1.0 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.5 |
1.5 |
1.0 |
1.0 |
0.5 |
1.0 |
|
2.0 |
2.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
float16 accuracy#
Maximum error in units in the last place (ULPs) for float16:
Function |
CPU |
NVIDIA GPU |
TPU v2–v5e |
TPU v5p |
TPU v6e |
TPU 7x |
|---|---|---|---|---|---|---|
1.5 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
2.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.5 |
1.0 |
0.5 |
0.5 |
0.5 |
0.5 |
|
1.5 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.5 |
0.5 |
1.0 |
1.0 |
0.5 |
0.5 |
|
1.0 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.0 |
1.0 |
1.0 |
1.0 |
0.5 |
0.5 |
|
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.0 |
1.0 |
0.5 |
0.5 |
1.0 |
1.0 |
|
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
|
1.0 |
1.0 |
1.0 |
1.0 |
0.5 |
0.5 |
14.0 |
14.0 |
7.5 |
7.5 |
7.5 |
7.5 |
|
2.5 |
1.0 |
1.0 |
1.0 |
0.5 |
0.5 |
|
|
2.5 |
1.0 |
1.0 |
1.0 |
0.5 |
0.5 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
2.0 |
2.0 |
1.5 |
1.0 |
1.0 |
1.0 |
|
2.0 |
2.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.0 |
0.5 |
1.0 |
1.0 |
1.0 |
1.0 |
|
0.5 |
0.5 |
1.0 |
1.0 |
1.0 |
1.0 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
0.5 |
0.5 |
1.0 |
1.0 |
0.5 |
0.5 |
|
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.5 |
1.5 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.5 |
1.5 |
1.0 |
1.0 |
1.0 |
1.0 |
|
1.5 |
1.5 |
1.5 |
1.5 |
1.5 |
1.5 |
|
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
|
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
float32 accuracy#
Maximum error in units in the last place (ULPs) for float32:
Function |
CPU |
NVIDIA GPU |
TPU v2–v5e |
TPU v5p |
TPU v6e |
TPU 7x |
Notes |
|---|---|---|---|---|---|---|---|
1.5 |
1.5 |
5.0 |
5.0 |
4.0 |
5.0 |
||
4.5 |
2.5 |
4031.0 |
61.0 |
4.5 |
5.0 |
||
2.0 |
1.5 |
5.0 |
5.0 |
4.5 |
4.5 |
||
3.5 |
2.0 |
4034.5 |
62.5 |
3.5 |
3.5 |
||
4.0–5.5 |
1.5 |
2.5 |
2.5 |
2.5 |
2.5 |
CPU bound depends on AMD vs Intel |
|
0.5 |
3.0 |
3.5 |
3.5 |
3.5 |
3.5 |
||
3.0 |
3.5 |
2183.5 |
43.0 |
3.5 |
3.5 |
||
7.0 |
8.0 |
8.0 |
8.0 |
8.0 |
8.0 |
||
11.0 |
15.5 |
15.5 |
15.5 |
15.5 |
15.5 |
||
0.5 |
1.5 |
4.5 |
4.5 |
1.5 |
1.5 |
||
0.5 |
2.0 |
3.5 |
3.5 |
3.5 |
3.0 |
||
25.0 |
2.5 |
93.5 |
99.0 |
59.0 |
59.5 |
||
7.0 |
6.5 |
7.5 |
8.5 |
1.5 |
1.5 |
||
65.0 |
65.0 |
427.0 |
65.5 |
65.0 |
65.5 |
||
66.0 |
66.5 |
145.0 |
157.0 |
124.5 |
125.0 |
||
|
4.0 |
5.0 |
5.5 |
5.0 |
5.0 |
5.0 |
|
1.5 |
2.0 |
116.0 |
109.5 |
64.5 |
65.0 |
||
|
1.5 |
2.0 |
1.5 |
1.5 |
1.5 |
1.5 |
|
68.5 |
69.0 |
141.5 |
133.0 |
90.0 |
90.0 |
||
6.5 |
1.5 |
1772.0 |
1357.5 |
3.5 |
3.5 |
||
|
6.5 |
1.5 |
2.0 |
2.0 |
2.0 |
2.0 |
|
1.5 |
1.0 |
4030.5 |
62.0 |
2.5 |
2.5 |
||
3.0 |
1.0 |
4034.0 |
63.0 |
3.0 |
3.0 |
||
2.5 |
2.0 |
5159.0 |
57.5 |
2.5 |
2.5 |
||
2.5 |
4.0 |
243.0 |
124.0 |
65.5 |
64.0 |
||
0.5 |
1.0 |
198.0 |
40.0 |
1.5 |
1.5 |
||
1.0–2.0 |
2.0 |
2.5 |
2.5 |
1.5 |
1.0 |
CPU bound depends on AMD vs Intel |
|
0.5 |
1.5 |
3.5 |
3.5 |
3.5 |
3.5 |
||
25.0 |
3.0 |
1794.0 |
1332.5 |
59.0 |
59.5 |
||
0.5 |
1.0 |
3.0 |
3.0 |
2.0 |
2.0 |
||
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
0.5 |
||
0.5 |
3.5 |
6.5 |
7.0 |
5.5 |
5.5 |
||
5.0 |
5.5 |
1365.5 |
92.0 |
1.5 |
1.5 |
||
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
||
1.5 |
2.0 |
3.5 |
3.5 |
2.5 |
2.5 |
||
3.0 |
2.5 |
6213.0 |
57.0 |
3.0 |
3.0 |
||
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
1.0 |
||
2.5 |
3.5 |
4.0 |
4.0 |
4.0 |
3.5 |
||
3.5 |
4.0 |
4.0 |
4.0 |
4.5 |
4.5 |
float64 accuracy#
Maximum error in units in the last place (ULPs) for float64.
Note
TPUs have no true float64 hardware. While bounds for 16-bit types and unary float32 operations are exhaustive, for binary float32 operations and float64 these are empirical bounds.
Function |
CPU |
NVIDIA GPU |
|---|---|---|
1.5 |
1.5 |
|
3.5 |
2.5 |
|
1.5 |
2.5 |
|
2.5 |
2.5 |
|
3.5 |
2.5 |
|
0.5 |
1.5 |
|
2.5 |
3.5 |
|
7.5 |
7.5 |
|
10.5 |
7.5 |
|
0.5 |
1.5 |
|
0.5 |
1.5 |
|
496.0 |
2.5 |
|
2.5 |
2.5 |
|
500000.0 |
500000.0 |
|
350.0 |
350.0 |
|
|
2.5 |
2.5 |
2.0 |
1.5 |
|
719.0 |
719.0 |
|
4.5 |
1.5 |
|
0.5 |
1.5 |
|
2.0 |
1.5 |
|
1.5 |
1.5 |
|
3.5 |
4.5 |
|
0.5 |
0.5 |
|
1.5 |
1.5 |
|
0.5 |
2.5 |
|
496.0 |
2.5 |
|
0.5 |
0.5 |
|
0.5 |
0.5 |
|
0.5 |
2.5 |
|
7.0 |
3.5 |
|
1.0 |
1.0 |
|
1.5 |
1.5 |
|
2.0 |
2.5 |
|
1.0 |
1.0 |
|
2.0 |
2.0 |
|
3.0 |
3.0 |