cuda-oxide 中文文档#

cuda-oxide 标志

cuda-oxide 是一个实验性的 Rust 到 CUDA 编译器,让你能够用安全(近乎安全)、地道的 Rust 编写(SIMT)GPU 内核。它将标准 Rust 代码直接编译为 PTX——无需 DSL,无需外部语言绑定,只需 Rust。

备注

本书假定读者熟悉 Rust 编程语言,包括所有权、trait 和泛型。后续关于异步 GPU 编程的章节还假定读者了解 async/.await 以及 tokio 等运行时。

如需复习,请参阅 Rust 程序设计语言Rust 示例异步编程指南


项目状态#

v0.1.0 版本是一个早期 alpha 阶段:预期会遇到 bug、不完整的功能和 API 变更,我们正在努力改进。我们希望你能试用它,并通过分享使用体验来帮助塑造其发展方向。


🚀 快速开始#

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();

    let a = DeviceBuffer::from_host(&stream, &[1.0f32; 1024]).unwrap();
    let b = DeviceBuffer::from_host(&stream, &[2.0f32; 1024]).unwrap();
    let mut c = DeviceBuffer::<f32>::zeroed(&stream, 1024).unwrap();

    module
        .vecadd(&stream, LaunchConfig::for_num_elems(1024), &a, &b, &mut c)
        .unwrap();

    let result = c.to_host_vec(&stream).unwrap();
    assert_eq!(result[0], 3.0);
}

安装好前提条件后,使用 cargo oxide run vecadd 构建并运行。

备注

#[cuda_module] 将生成的设备工件嵌入到宿主二进制文件中,并生成一个类型化的 kernels::load 函数以及每个内核一个启动方法。当你需要加载特定的 sidecar 工件或构建自定义启动代码时,仍可使用更低层的 load_kernel_modulecuda_launch! API。


为什么选择 cuda-oxide?#

🦀 GPU 上的 Rust

使用 Rust 的类型系统和所有权模型编写 GPU 内核。安全性是首要目标,但 GPU 有其微妙之处——请阅读安全模型

💎 一个 SIMT 编译器

这不是 DSL。它是一个自定义的 rustc 代码生成后端,将纯 Rust 编译为 PTX。

⚡ 异步执行

将 GPU 工作组合为惰性的 DeviceOperation 图。跨流池调度。使用 .await 等待结果。