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.

Source IDENTITY_PATHS.md.

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.

  1. August 11, 2026

    Mojo 1.0 released

  2. August 19

    mojolearn repository started

    Gradient boosted trees first, with the identity contract from day one.

  3. 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.

  4. 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.

  5. 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.

  6. September 5

    Release 0.5.0 ships the training code

    The wheel carries the training, transformer, and Mamba extensions.

  7. 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.

  8. 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.

  9. September 7

    Three vendors, one training run

    A byte level language model trained 128 steps with the same bits on NVIDIA, AMD, and Apple.

  10. 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.