NVIDIA anuncia CUDA Rust con cuda-oxide (SIMT) y cutile-rs (Tile) para núcleos de GPU seguros en tiempo de compilación

NVIDIA ha anunciado CUDA Rust, un impulso para hacer de Rust un lenguaje de primera clase para escribir núcleos de GPU. El código Rust ya podía iniciar núcleos CUDA, pero el cuerpo del núcleo normalmente tenía que escribirse en otro lugar. CUDA Rust cierra esa brecha con dos proyectos de código abierto de NVlabs: cuda-oxide para el modelo SIMT y cutile-rs para el modelo Tile más nuevo. Ambos compilan kernels de Rust de forma nativa y utilizan las reglas de propiedad de Rust para rechazar errores de alias en el momento de la compilación.

¿Es desplegable? Parcialmente. cutile-rs se publica en crates.io, se ejecuta en Rust 1.89+ estable y ya se usa en el motor de inferencia Grout de Hugging Face y en mistral.rs. El óxido de cuda es alfa temprano. Ambos proyectos se encuentran en fase alfa y no están confirmados para producción.

Por qué Rust para el kernel de GPU

La capa de sistemas de la IA, desde los motores de inferencia hasta los controladores y los tiempos de ejecución de los agentes, está cada vez más escrita en Rust. El controlador Nova Linux de NVIDIA está en Rust, NVIDIA Dynamo tiene un núcleo Rust y NVTX tiene enlaces Rust. El núcleo de la GPU fue la excepción.

Las dos pistas reflejan los dos modelos de programación que CUDA ya ofrece. SIMT es el modelo utilizado en CUDA C++ y numba-cuda: describe lo que hace un hilo y lanza miles de ellos. Tile es el modelo más nuevo, también disponible en C++ y Python: usted describe lo que hace un mosaico de datos y el compilador Tile IR maneja el mapeo de subprocesos y el diseño de la memoria. NVIDIA recomienda Tile primero, con SIMT para control explícito de memoria y subprocesos. La interoperabilidad entre idiomas planificada significa que elegir Rust no bloqueará a los desarrolladores en C++ o Python.

La vía SIMT: cuda-óxido

cuda-oxide es un backend de codegen rústico personalizado. Ruta #[kernel] funciona a través de Rust MIR, el marco comunitario Pliron IR y LLVM IR hasta PTX, luego entrega todo lo demás al backend estándar. NVIDIA escribió los dialectos de la GPU sobre Pliron.

Requisitos: Linux, una GPU con capacidad informática 8.0 o posterior, CUDA 12.x o posterior, sonido metálico con libclang y una cadena de herramientas nocturna fijada (nightly-2026-04-03). cargo oxide doctor comprueba la configuración y los nuevos andamios de cargo oxide, un programa de adición de vectores, con código de host y dispositivo en un solo archivo.

El argumento de seguridad se encuentra en la firma del núcleo. Las entradas a y b son porciones compartidas ordinarias. La salida c es un DisjointSlice, un tipo que le da a cada hilo acceso exclusivo a su propio elemento. Un simple y mut [f32] necesitaría que cada hilo contenga el mismo préstamo mutable, lo cual Rust rechaza. c.get_mut(idx) devuelve una opción, por lo que el acceso fuera de límites se convierte en una rama manejada. A #[launch_contract] El atributo declara la forma del bloque y el método prepare_vecadd generado valida la configuración de lanzamiento antes de que se ejecute el lanzamiento seguro.

The Tile Track: cutile-rs

cutile-rs funciona un nivel más alto. Cada bloque de mosaico ejecuta el cuerpo del kernel una vez como un único subproceso lógico sobre un subtensor, y el compilador decide cuántos subprocesos de GPU reales lo respaldan. El #[cutile::module] La macro incorpora el AST del kernel en el binario del host y lo compila JIT a través de CUDA Tile IR cuando se inicia el kernel por primera vez.

Los requisitos son más ligeros: capacidad informática 8.0 o posterior, CUDA 13.3, Rust 1.89 estable o posterior y Linux, sin LLVM nocturno ni personalizado. La configuración es nueva, luego agrega cutile.

La partición .del lado del host ([128]) la llamada hace 3 trabajos. Le otorga a cada mosaico la propiedad exclusiva de su fragmento de 128 elementos, fija la cuadrícula en 1024/128 = 8 mosaicos y proporciona el ancho constante de mosaico B. Los tensores de entrada usan -1 como una dimensión dinámica resuelta en el lanzamiento. El lanzador generado toma posesión de todos los tensores y los devuelve cuando finaliza la GPU. Nada se ejecuta hasta que .sync_on(&stream); todo lo anterior es una descripción vaga registrada en una cadena.