Open source
mojolearn
A GPU machine learning library I wrote in Mojo. One source builds for Apple, NVIDIA, and AMD GPUs, and its default mode returns the same bits on all of them, for training and for inference.
From the paper
Bitwise-Identical Machine Learning Across Metal, CUDA, and HIP
The same machine-learning workload can produce different bits on different GPUs, changing predictions, learned models and subsequent training updates. mojolearn is a GPU machine-learning library whose default identical mode produces bitwise-identical results across verified Apple, NVIDIA and AMD GPUs and x86-64 and Arm CPUs. Results agree bit for bit, not merely within a numerical tolerance. It supports training and inference for 57 machine-learning algorithms in 12 families, from decision trees to neural networks. Neural models trained in other frameworks can be served with identical outputs across vendors, and training workloads can be handed off between GPU vendors mid-run, or shared by GPUs of different vendors at once, while maintaining bitwise identity. Neural training and inference run in full FP32 floating-point arithmetic, without reducing the computation to integers. To my knowledge, I am the first to enable these capabilities.
One Mojo codebase implements these algorithms across Metal, CUDA and HIP under a shared numerical contract. Mojo compiles code for different GPUs, but maintaining that contract and implementing the algorithms is original work.
The work
What it took to build
Counted from the public repository on September 25, 2026. Lines are non-blank lines.
520,000 lines
Of Mojo in the library itself, plus about 100,000 more in Mojo checks and benchmarks
265,000 lines
Of Python for bindings, packaging, test harnesses, and tooling
1,900
GPU kernel launch sites across 1,591 Mojo source files
57
Machine learning algorithms in 12 families, trees to neural networks
5,000+
Commits since the repository started on August 19, 2026
25
Releases on PyPI, for macOS on Apple silicon and Linux x86-64
Where the compiler ends and the work begins
Mojo compiles one kernel source to each GPU's own machine code, Metal on Apple, PTX on NVIDIA, and AMDGPU on AMD. That solves portability. It does not make the results match. Each backend makes its own choices about rounding, instruction selection, and math libraries, and each GPU schedules threads in its own order. Floating point addition is not associative, so any of those choices can move a bit, and in a decision tree one moved bit can become a different split and a different model.
mojolearn sits in that seam. It implements the algorithms as GPU kernels, and it controls, kernel by kernel, everything the compiler and the hardware would otherwise decide differently per vendor. The project keeps a public ledger of 96 numbered pathways where a bit can move, each with what identical mode does about it. A few of them follow.
One source
One Mojo source, three GPU backends, one set of bits
The compiler handles portability. Matching bits is the library's job.
One Mojo source
Kernels plus a shared numerical contract
Apple · Metal
M series Macs
NVIDIA · CUDA
RTX 4090, H100
AMD · HIP
MI300X, MI325X
Same bits
Predictions, trained models, checkpoints
The ledger
Where a bit can move, and what identical mode does about it
Six of the 96 numbered pathways in the project's identity ledger.
Float atomics
Threads add in whatever order they arrive, and float addition depends on order.
Accumulate in fixed point integers, which add the same in any order.
Summation order
Block sizes, lane counts, and core counts decide how partial sums combine. An AMD wavefront is 64 lanes, an NVIDIA warp is 32.
Pin every width that is really a summation order to one value on every vendor.
Fused multiply add
Whether a * b + c rounds once or twice is a code generation choice that differs by backend.
Spell the fused operation explicitly, so every backend rounds once.
Square root and transcendentals
sqrt is not correctly rounded on NVIDIA, and exp and log come from each vendor’s own math library.
Use the library’s own portable routines, the same code on every host and device.
Ties and signed zero
max(+0, −0) returns a different zero on Apple than on NVIDIA and AMD, and ties can be broken by arrival order.
Fix every tie break and every zero rule by construction.
Closed vendor libraries
A vendor matrix multiply picks its own tile shape and split, and a split is a summation order.
Route identical mode through the library’s own kernels, with a pinned order.
Handing training off between vendors
The strongest test of identity is to stop a training run on one vendor's GPU and finish it on another's. On September 6, 2026, a small byte level language model (two transformer blocks, 34,944 FP32 parameters, real text) was trained for 64 steps on NVIDIA, saved, and resumed on AMD, and the same in the other direction. Both continuations matched an uninterrupted run on the original device through step 128, checked across all parameters, gradients, optimizer moments, losses, and the checkpoint bytes. A day later the same 128 step run matched byte for byte on NVIDIA, AMD, and Apple.
Each step reached PyPI with a DOI that archives its evidence. The first release,0.1.0 on August 23, already trained tree and classical models to the same bits on every supported vendor, and0.3.0 on August 30 added a Linux wheel with NVIDIA and AMD GPU binaries. Neural network training (embedding, transformer forward and backward, cross entropy, and AdamW) was verified bitwise identical on Apple, NVIDIA, and AMD on September 3. Its code shipped in the 0.5.0 wheel on September 5, and0.6.0 on September 6 made training a public API, with that evidence in its archive. The handoff between vendors is archived in0.7.0 on September 9. Every version is listed under the project'sconcept DOI.
These are bounded results for the shapes and configurations recorded in the project's support matrix, and each claim is proven by stage level identity cards and sabotage tests rather than a final hash. Identity also has a cost. Identical mode gives up some speed to pin every order, which is why every family also ships a fast mode with no bit promise. This is a claim about where the code runs and what it returns, not about speed.
Timeline
From Mojo 1.0 to cross-vendor training in four weeks
Dates from release notes, tags, and the evidence records in the repository.
August 11, 2026
Mojo 1.0 released
August 19
mojolearn repository started
Gradient boosted trees first, with the identity contract from day one.
August 23
Release 0.1.0 on PyPI and the first DOI
Bitwise identical training for trees and classical models. The wheel is for Apple silicon; NVIDIA and AMD build from source.
August 30
Release 0.3.0 adds NVIDIA and AMD binaries
A Linux wheel with CUDA (sm_80, sm_90a, sm_120a) and HIP (gfx90a, gfx942, gfx1100) builds.
September 3
Neural network training is bitwise identical on Apple, NVIDIA, and AMD
Embedding, transformer forward and backward, cross entropy, and AdamW, eight steps with one hash on all three. The same day an Apple M4 and an AMD MI325X wrote the same checkpoint file, byte for byte.
September 5
Release 0.5.0 ships the training code
The wheel carries the training, transformer, and Mamba extensions.
September 6
Release 0.6.0 makes training a public API
mojolearn.training with optimizers, losses, and the small trainer, plus an AMD Linux wheel. Its archive holds the September 3 evidence.
September 6
Training handed off between NVIDIA and AMD mid-run
Stopped at step 64 on one vendor, resumed on the other, identical to step 128 in both directions.
September 7
Three vendors, one training run
A byte level language model trained 128 steps with the same bits on NVIDIA, AMD, and Apple.
September 9
Release 0.7.0 archives the handoff
The byte level language model trainer on Linux, with the cross-vendor resume records in its archive.