FP64-accurate matrix multiplication from BF16 hardware via Ozaki Extract in JAX
Project description
ozaki-jax
FP64-accurate linear algebra on BF16/FP32-oriented hardware (e.g. TPU) using Ozaki Extract in JAX.
ozaki-jax features accurate matmul with higher-level routines for Gram matrices, residuals, and iterative-refinement solves.
Install
# inside an active environment
uv pip install -e .
Optional TPU dependency:
uv pip install -e ".[tpu]"
Public API
from ozaki_jax import gram, matmul, matmul_numpy, residual, solve
matmul(A, B, ...): accurate matrix multiply with host or on-device Ozaki pipelines.matmul_numpy(A, B, ...): NumPy-only mirror for host path and testing.gram(A, ...): computes symmetricA.T @ A.residual(A, x, b, ...): computes accurateb - A @ x.solve(A, b, ...): iterative refinement solve with FP32 factorization plus accurate residuals.
Input/output typing:
- NumPy input -> NumPy output
- JAX input -> JAX output
- Mixed NumPy/JAX inputs are rejected
Quick Start
1) Accurate Matmul (Default Host Pipeline)
import numpy as np
from ozaki_jax import matmul
A = np.random.randn(256, 256)
B = np.random.randn(256, 256)
C = matmul(A, B)
2) On-device Pipeline
import jax
from ozaki_jax import matmul
jax.config.update("jax_enable_x64", True)
C = matmul(A, B, pipeline="ondevice", accumulation="fused")
# or:
C2 = matmul(A, B, pipeline="ondevice", accumulation="bf16_interleaved")
3) Gram / Residual / Solve
import numpy as np
import jax
from ozaki_jax import gram, residual, solve
jax.config.update("jax_enable_x64", True)
A = np.random.randn(256, 256)
b = np.random.randn(256)
x = solve(A, b) # default: residual_mode="f64"
r = residual(A, x, b) # default: mode="f64"
G = gram(A) # default: mode="f64", symmetric result
Matmul Options
matmul(A, B, n_slices=8, safe_mode="raise", pipeline="host", accumulation="fused", precision="high")
Pipeline:
pipeline="host"(default): FP64 host extraction + triangular pair scheduling.pipeline="ondevice": FP64 input -> FP32 hi/lo split + on-device extract/GEMM/accumulation.
On-device accumulation (pipeline="ondevice" only):
fused(default): split + extraction + GEMMs + 2Sum in one JIT call.bf16_interleaved: BF16-cast extracted slices, interleaved GEMM+2Sum.ondevice: separate on-device 2Sum accumulation after GEMMs.host: transfer products and accumulate on host in FP64.
On-device precision presets (precision=):
high->(n_hi=4, n_lo=1)-> 24 GEMMsmedium->(n_hi=3, n_lo=1)-> 15 GEMMsmax->(n_hi=5, n_lo=4)-> 65 GEMMs- custom tuple
(n_hi, n_lo)is supported
Safety behavior (safe_mode=):
raise(default): raisesValueErrorwhen preflight fails.fallback: returns plain FP64A @ Bwhen preflight fails.
Gram / Residual / Solve Details
gram(A, precision="high", accumulation="bf16_interleaved", mode="f64")
- Computes
A.T @ A, then symmetrizes via(G + G.T) / 2. mode="f64"(default): native FP64 matmul, highest accuracy.mode="ozaki": uses Ozaki pipeline andprecision/accumulation.
residual(A, x, b, precision="high", accumulation="bf16_interleaved", mode="f64")
- Computes
b - A @ xfor vector or matrixx. - Supports rectangular
A. mode="f64"(default) ormode="ozaki".
solve(A, b, precision="high", accumulation="bf16_interleaved", max_iterations=3, residual_mode="f64")
- Solves
A x = busing iterative refinement. - Uses FP32 solve steps with accurate residual recomputation.
residual_mode="f64"(default): best accuracy and usually best convergence.residual_mode="ozaki": available when FP64 throughput is constrained.
x64 Requirement
Enable x64 before using:
matmul(..., pipeline="ondevice", accumulation in {"fused", "bf16_interleaved"})gram()residual()solve()
import jax
jax.config.update("jax_enable_x64", True)
Safety and Exactness
Preflight checks (for matmul/matmul_numpy) include:
- Rank/shape compatibility
- Finite inputs (no
NaN/Inf) - Mantissa/extract budget constraints
- BF16->FP32 exact inner-product bound
Core exactness condition for BF16-bounded slice values:
K * (2^p - 1)^2 < 2^24
In the default BF16 setting (p = 7), this gives K <= 1040.
Validation and Benchmark Scripts
Run from repo root with uv run:
# Core accuracy/validation
uv run python benchmarks/ci_cpu_validate.py
uv run python benchmarks/ci_gram_validate.py
uv run python benchmarks/ci_solve_validate.py
uv run python benchmarks/tpu_validate.py
uv run python benchmarks/tpu_full_validate.py
# Performance / profiling sweeps
uv run python benchmarks/bench_bf16_interleaved.py
uv run python benchmarks/bench_bf16_broadcast.py
uv run python benchmarks/bench_interleaved.py
uv run python benchmarks/tpu_phase_profile.py
uv run python benchmarks/tpu_scaling_sweep.py
Limitations
- Unblocked exactness model still limits supported
Kfor strict guarantees. - CPU execution does not represent TPU BF16/MXU behavior.
- TPU speedups depend on matrix size, backend, and accumulation mode; profile on target hardware.
References
- Mukunoki, D., Ogita, T., & Imamura, T. (2020). "DGEMM using Tensor Cores, and Its Accurate and Reproducible Versions." ISC High Performance 2020.
- Mukunoki, D. (2025). "Ozaki Scheme-Based Accurate Matrix Multiplication on FP8 Tensor Cores." arXiv:2508.00441
- Ozaki, K., Ogita, T., Oishi, S., & Rump, S.M. (2012). "Error-Free Transformations of Matrix Multiplication by Using Fast Routines of Matrix Multiplication and Its Applications." Numerical Algorithms, 59(1).
License
Apache 2.0
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ozaki_jax-0.6.0.tar.gz.
File metadata
- Download URL: ozaki_jax-0.6.0.tar.gz
- Upload date:
- Size: 77.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa86f91b8daf5b733dc2b708f19253e0fffe4f3c0905aa08e8ed47ce35414415
|
|
| MD5 |
b127b96f44d76ed600ab25c3ef6cd22c
|
|
| BLAKE2b-256 |
1538f3ffe7b80d9787840343b77e2ebd96b20d7c1ba171181a9ff78fa29e5dca
|
File details
Details for the file ozaki_jax-0.6.0-py3-none-any.whl.
File metadata
- Download URL: ozaki_jax-0.6.0-py3-none-any.whl
- Upload date:
- Size: 28.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bfd4414100f8543d7abb164322c0596f62009a98a37a4a09d370fc5baf6e3965
|
|
| MD5 |
2d8900a1610fcdda66bfde67543c7014
|
|
| BLAKE2b-256 |
1665813a7f7f200ea69d8ad6f3445b677814be7028c3c63229624e384c7ac5c3
|