COOLJAPAN
← All posts

OxiCUDA 0.5.0 Released — F64 PTX Correctness, Mixed-Precision GEMM Fixes, and Zero unwrap() Left

OxiCUDA 0.5.0, the sovereign GPU-compute layer for the COOLJAPAN ecosystem, fixes F64-precision PTX codegen bugs that made ptxas reject elementwise and reduction kernels, closes a mixed-precision GEMM accumulator bug, and hits zero unwrap()/expect() in library code. 38,622 tests, ~1.30M SLoC, 73 crates.

release oxicuda cuda gpu pure-rust ptx blas gemm precision bugfix

A GPU kernel that ptxas refuses to assemble fails loudly. A GPU kernel that assembles fine and quietly computes the wrong answer is far more dangerous — 0.5.0 found and fixed one of each.

Today we released OxiCUDA 0.5.0 — a correctness release that fixes F64-precision PTX code generation across elementwise and reduction kernels, closes a mixed-precision GEMM bug that was silently corrupting results instead of erroring, and eliminates the last 42 .expect() call sites anywhere in the workspace’s library code.

No CUDA SDK. No nvcc. No C/C++ toolchain. OxiCUDA is a type-safe, memory-safe, pure-Rust replacement for the entire NVIDIA CUDA Toolkit software stack — cuBLAS, cuDNN, cuFFT, cuSPARSE, cuSOLVER, cuRAND and more, across 73 crates and ~1.30M lines of safe Rust. libcuda.so / nvcuda.dll is loaded dynamically at runtime via libloading; nothing about building OxiCUDA requires the CUDA SDK or a C/C++ compiler. The result compiles to a single static binary and runs everywhere the driver is present, from Turing through Blackwell.

Why OxiCUDA 0.5.0 is a game changer

NVIDIA’s official stack still asks you to accept, on faith:

OxiCUDA 0.5.0 ends all of that.

Technical Deep Dive

  1. Foundation — oxicuda-driver, oxicuda-memory, oxicuda-launch, oxicuda-runtime. Dynamic driver loading via libloading, an RAII DeviceBuffer<T>, and the type-safe launch! macro sit underneath everything else. None of 0.5.0’s fixes touched this layer — it’s been through two prior on-device validation sweeps (0.4.0, 0.4.1) and held steady.
  2. PTX codegen & autotuner — oxicuda-ptx, oxicuda-autotune. This is where 0.5.0’s core fixes live. ElementwiseTemplate and ReductionTemplate generate the actual PTX text for every elementwise op and block reduction across F16/BF16/F32/TF32/F64, and this release is the first time the F64 path assembles correctly — while also refusing to generate F64 for the handful of ops PTX itself only defines at F32.
  3. Linear algebra & deep learning — oxicuda-blas, oxicuda-dnn. Full BLAS L1/L2/L3 with SIMT/Tensor-Core/Split-K GEMM dispatch, plus convolution, attention, normalization, and quantization for DNN. The new GpuFloat::to_accumulator_bits() fix lives here, correcting how GEMM’s alpha/beta epilogue scalars are encoded across every mixed-precision path.
  4. Scientific computing and the wider domain layer. oxicuda-fft, oxicuda-sparse, oxicuda-solver, and oxicuda-rand cover the cuFFT/cuSPARSE/cuSOLVER/cuRAND surface; above that sit dozens more domain crates — generative diffusion (oxicuda-gen), graph neural networks (oxicuda-gnn), state-space models (oxicuda-mamba), vision transformers (oxicuda-vision), causal inference (oxicuda-causal), PDE solvers (oxicuda-pde), and more — all downstream of oxicuda-ptx and oxicuda-blas, so they inherit this release’s precision fixes without a single line of their own code changing.

Getting Started

Add OxiCUDA and opt into the subsystems you need:

cargo add oxicuda --features blas

Default features are driver, memory, and launch. Every subsystem is its own flag (ptx, autotune, blas, dnn, fft, sparse, solver, rand, primitives, vulkan, metal, webgpu, rocm, level-zero, and full for everything) — plus gpu-tests if you have real GPU hardware and want to exercise this release’s F64 and mixed-precision GEMM fixes yourself.

A complete GEMM, end to end:

use oxicuda::prelude::*;

fn main() -> Result<(), oxicuda::Error> {
    // Initialize driver and select GPU device
    let device = Device::get(0)?;
    let ctx = Context::new(device)?;
    let stream = Stream::new(&ctx)?;

    // Allocate device memory
    let mut d_a = DeviceBuffer::<f32>::zeroed(1024)?;
    let mut d_b = DeviceBuffer::<f32>::zeroed(1024)?;
    let mut d_c = DeviceBuffer::<f32>::zeroed(1024)?;

    // Copy host data to device
    d_a.copy_from_host(&host_a)?;
    d_b.copy_from_host(&host_b)?;

    // Launch a GEMM: C = alpha * A @ B + beta * C
    let handle = BlasHandle::new(&stream)?;
    handle.gemm(
        Transpose::None, Transpose::None,
        m, n, k,
        1.0f32,            // alpha
        &d_a, lda,
        &d_b, ldb,
        0.0f32,            // beta
        &mut d_c, ldc,
    )?;

    stream.synchronize()?;

    // Copy result back to host
    let mut result = vec![0.0f32; m * n];
    d_c.copy_to_host(&mut result)?;
    Ok(())
}

On a machine with an NVIDIA GPU, run the same validation this release’s fixes were checked against:

cargo test --features gpu-tests

What’s New in 0.5.0

Tips

This is the foundation

OxiCUDA is the GPU layer beneath the rest of the COOLJAPAN ecosystem. Its own architecture diagram puts SciRS2, OxiONNX, TrustformeRS, and ToRSh directly on top of it, with OxiBLAS and OxiFFT rounding out the list of projects that lean on this stack — and the oxicuda crate itself is an umbrella re-export over all 73 crates, so a single cargo add oxicuda pulls in whichever subsystem a dependent project needs. The F64 PTX fixes and the GEMM precision fix in 0.5.0 are live under every one of them today, without a single line of their own code changing.

Repository: https://github.com/cool-japan/oxicuda

Star the repo if you believe GPU numeric bugs should fail loud at generation time instead of silently shipping a wrong answer to production. Every star tells us to keep building.

Pure Rust GPU computing is here — and as of 0.5.0, its double-precision path finally works as well as its single-precision one.

KitaSan at COOLJAPAN OÜ July 14, 2026

↑ Back to all posts