CUDA Rust splits GPU kernel development into two tracks

Published: September 18, 2026

CUDA Rust arrived this month as two separate toolchains.

Both promise memory safety that the compiler checks before a single thread launches, and only one of them lets you keep the stable Rust your release pipeline already runs.

NVIDIA's developer blog laid out the pair on 8 September 2026 in Introducing CUDA Rust: Two Tracks for Writing GPU Kernels.

One track is cuda-oxide, an NVlabs rustc backend that compiles ordinary #[kernel] functions straight to CUDA PTX. The other is cutile-rs, a tile based system that partitions tensors before launch and JIT compiles each kernel through CUDA Tile IR.

Banner from the cuda-oxide repository, one of the two CUDA Rust tracks, reading write CUDA SIMT kernels in pure Rust.

The two projects share a host runtime, cuda-core and cuda-async, so swapping the kernel frontend does not mean rewriting the host side of your GPU code.

Adopting Rust for GPU kernels now means choosing which constraint to carry: a pinned nightly compiler with a custom backend, or a tile based programming model on stable Rust.

What CUDA Rust asks of your build

cuda-oxide wants a pinned Rust nightly with rust-src, rustc-dev and llvm-tools, a CUDA 13 driver, and LLVM 21 or newer, because it emits Hopper and Blackwell intrinsics that older LLVM releases cannot handle.

Neither project is a weekend port. cuda-oxide also needs clang 21 for its host bindings and the CUDA toolkit's cuRAND headers, and those bindings load libcuda at runtime against a CUDA 13 driver.

Its compilation path is deliberately long: Rust, then Rust MIR, then the Pliron IR framework, then LLVM IR, then PTX. The project is alpha, its README says to expect bugs, incomplete features and API breakage, and it has been tested on Ubuntu 24.04.

Setup is scripted rather than manual. cargo oxide doctor checks the toolchain, CUDA, LLVM and codegen backend before you build, and a matching subcommand runs your examples under NVIDIA Compute Sanitizer.

cutile-rs asks for stable Rust 1.89 or later and CUDA 13.3, with no custom compiler to build and no nightly pin to babysit. It ships as the cutile crate, so adoption is a dependency bump rather than a compiler project.

Toolchain floors by hardware

Support stops below sm_80. CUDA 13.2 covers Ampere, Ada and Blackwell parts, Hopper needs 13.3, and FP4 packing and block scaled MMA need the newer toolkit as well.

Who already runs this

The cuTile Rust logo from the NVlabs cutile-rs repository.

Hugging Face's Grout inference engine is built with cutile-rs, and the project points to it as a reference for production kernel call sites.

The accompanying paper reports Grout reaching 171 tokens per second for a Qwen3 4B model on an RTX 5090, and 82 tokens per second for Qwen3 32B on a B200.

cutile-rs applies the same ownership rules to synchronous launches, asynchronous pipelines and CUDA graph replay, so the safety story does not depend on which execution style you pick.

cuda-oxide has no comparable production story yet. It does ship more than 190 examples, cross crate kernels, device side LTO for Blackwell, and a GEMM example the project presents as a speed of light implementation.

Where the safety actually sits

cuda-oxide gives device code a DisjointSlice and lets a launch contract turn the aliasing proof into a checked launch, so overlapping access is rejected before the driver sees anything.

Launches without a contract stay unsafe by design, because the launch configuration is passed as raw data that the compiler cannot verify.

The same backend reaches into existing code: device FFI lets a Rust kernel call C++ CCCL warp level reductions under LTO, and MathDx bindings cover thread level FFT and block level GEMM.

cutile-rs extends ownership across the launch boundary instead. Mutable tensors are partitioned into disjoint pieces, shared inputs stay read only, and the generated launcher holds that ownership while GPU work is in flight.

The paper behind it, Fearless Concurrency on the GPU, reports the cost of that discipline as unmeasurable on B200 hardware. Safe persistent GEMM reaches 2.07 PFlop/s at M=N=K=8192, within 0.3% of the equivalent low level Tile IR variant, and element wise work reaches 7 TB/s, about 91% of peak memory bandwidth.

Three things to settle before you choose

1. Buy the boring compiler first. If a kernel has to ship this quarter, write it in cutile-rs, where the compiler is a version number you already track, and spend the saved effort on Rust fundamentals for your team.

2. Isolate the nightly track in its own workspace and its own CI job. A pinned nightly, a custom codegen backend and an LLVM floor are three ways a build can break without a line of your own code changing, and pinning them explicitly in your CI pipeline is cheaper than finding out during a release. Keep that track off the release path until the project leaves alpha.

3. Define the kernel boundary, not the frontend. NVIDIA says it plans interoperability between the Rust tracks and CUDA C++ and CUDA Python, and cuda-oxide already ships an example that chains a tile kernel and a SIMT kernel on the same stream over shared device tensors. Kernel level interop inside a single launch is still being worked out, which is why the seam between host code and kernels should not assume one frontend forever, the same way you would treat any early architecture bet.

The assumption that just changed

The old assumption was that the kernel is the one part of a GPU codebase that has to stay in C++, with Rust confined to the service running around it.

The new reality is that the kernel is expressible in Rust, and the work you carry moves from memory handling to the toolchain and programming model you picked. That is a smaller risk than it sounds, because both tracks share the runtime underneath them.

So if a kernel is written once and reused for years, which cost is easier to defend in a design review: a pinned nightly compiler, or a tile shaped rewrite of the algorithm?