← EasyTool.me

CUDA-oxide 开源实测:NVIDIA 官方用 Rust 写 CUDA 内核

Published: 2026-05-12 Reading: 7 min AI / GPU / Rust

2026 年 5 月 11 日 NVIDIA Labs 在 GitHub 上开源了 CUDA-oxide — 一个实验性的 Rust-to-CUDA 编译器。这不是又一个 DSL 也不是 Rust 绑定的 CUDA 库,而是一个真正的 rustc 代码生成后端,让你用纯 Rust 写 GPU 内核,编译出来就是 PTX(NVIDIA GPU 的底层指令集),直接跑在 CUDA 上。

消息一出两小时内登上 Hacker News 首页拿到 130+ 分,社区反应非常热烈。对 Rust 社区来说这是里程碑式的一步 — 从此 GPU 编程可以和 Rust 的类型系统、所有权模型、无惧并发的承诺直接挂钩了。

CUDA-oxide 到底是什么

很多人看到"Rust-to-CUDA"第一反应是"哦,又一个 Rust bindings for CUDA"。完全不对。

CUDA-oxide 的工作原理是这样的:

关键区别:你没有写一行 C/C++,没有调 nvcc,没有 FFI 绑定。Rust 代码直接变成了 GPU 指令。

编译管线:用 Rust 自己搓了一套 MLIR

CUDA-oxide 的编译管线很有意思。它没有直接走 LLVM 就完事了,而是用了 Pliron — 一个用 Rust 实现的 MLIR 风格的中间表示框架。完整路径是:

Rust 源码 → Rust MIR → Pliron IR → LLVM IR → PTX

中间那层 Pliron 起到了类似 MLIR 的多级降级作用,让编译器可以做各种 GPU 特定的优化(内存合并、共享内存分配、warp 级操作)。

有意思的是这也意味着 CUDA-oxide 理论上可以输出到其他后端。不过在现阶段 NVIDIA 的目标很明确:先把 CUDA 生态做好。

上手体验:写一个向量加法

来看代码。这是 CUDA-oxide 的基本写法:

use cuda_device::{cuda_module, kernel, thread, DisjointSlice};
use cuda_core::{CudaContext, DeviceBuffer, LaunchConfig};

#[cuda_module]
mod kernels {
    use super::*;

    #[kernel]
    fn vecadd(a: &[f32], b: &[f32], mut c: DisjointSlice<f32>) {
        let idx = thread::index_1d();
        let i = idx.get();
        if let Some(c_elem) = c.get_mut(idx) {
            *c_elem = a[i] + b[i];
        }
    }
}

fn main() {
    let ctx = CudaContext::new(0).unwrap();
    let stream = ctx.default_stream();
    let module = kernels::load(&ctx).unwrap();
    // ...
    module
        .vecadd(&stream, LaunchConfig::for_num_elems(1024),
                &a, &b, &mut c)
        .unwrap();
}

如果你是 Rust 开发者,这段代码读起来应该非常自然。注意几个设计细节:

最高光的功能:闭包也能当内核用

CUDA-oxide 支持泛型内核和闭包捕获,这是 C++ CUDA 里非常麻烦的事情:

#[kernel]
pub fn map<T: Copy, F: Fn(T) -> T + Copy>(
    f: F, input: &[T], mut out: DisjointSlice<T>
) { /* ... */ }

let factor = 2.5f32;
module
    .map::<f32, _>(
        &stream,
        LaunchConfig::for_num_elems(1024),
        move |x: f32| x * factor,
        &input, &mut output,
    )
    .unwrap();

闭包的捕获变量(这里 factor)会被自动标量化并作为内核参数传递。Rust 的泛型单态化在这里帮了大忙 — 每个闭包都是一个独特的类型,编译器可以完美优化。

异步 GPU 编程:DeviceOperation 组合

CUDA-oxide 的 cuda-async crate 提供了懒加载的异步操作图:

use cuda_async::device_operation::DeviceOperation;

module
    .map_async::<f32, _>(
        LaunchConfig::for_num_elems(1024),
        move |x: f32| x * factor,
        &input, &mut output,
    )?
    .sync()?;
// 或者 .await?

多个 DeviceOperation 可以组合成图,跨 stream pool 调度,最后通过 .await 异步等结果。这对需要频繁启动小内核的训练或推理场景非常实用。

安全模型:GPU 内核的 safe Rust 有多远

CUDA-oxide 的安全模型是项目最值得关注的部分。Rust 的所有权模型在 CPU 上保证了内存安全,但 GPU 有它的特殊性:

目前 CUDA-oxide 还在 alpha 阶段,安全模型在 官方文档中有详细讨论。NVIDIA 团队明确说"安全是一等目标",但也承认 GPU 有"细微之处"。

安装和环境要求

目前只支持 Linux(Ubuntu 24.04 已验证),而且要求比较多:

安装方法:

cargo install --git https://github.com/NVlabs/cuda-oxide.git cargo-oxide
cargo oxide doctor  # 检查环境
cargo oxide run vecadd  # 跑第一个例子

项目提供了 46 个示例从 vecadd 到矩阵乘法到 MLP 推理,覆盖了大部分常用模式。

社区怎么看

HN 上的讨论集中在几个方面:

也有人指出了一个关键局限:CUDA-oxide 仍然依赖 NVIDIA 闭源的 CUDA 运行时和驱动。Mojo 虽然画了开源的饼但 1.0 连 Windows 都不支持。从"实用"角度 CUDA-oxide 是当下最现实的 Rust GPU 方案。

总结

CUDA-oxide v0.1.0 是 alpha 质量 — 有 bug、功能不全、API 会变。但它是 NVIDIA 第一次官方出手把 Rust 纳入 CUDA 生态的第一步,方向和执行力都是对的。

如果你是 Rust 开发者想玩 GPU 编程,现在就可以上手体验。如果你在写 AI 推理库或高性能计算框架,这个项目值得关注 — 未来某个版本可能就 production-ready 了。

项目地址:github.com/NVlabs/cuda-oxide

官方文档:nvlabs.github.io/cuda-oxide

HN 讨论:news.ycombinator.com/item?id=48096692