NVIDIA a franchi une étape importante pour faire du Rust un langage de premier ordre dans CUDA. La société a présenté deux projets permettant d’écrire des kernels GPU directement en Rust et de les compiler en PTX : cuda-oxide, orienté vers le modèle traditionnel SIMT, et cutile-rs, basé sur la nouvelle approche CUDA Tile. Ces deux initiatives sont encore en développement, et NVIDIA informe qu’aucun n’est prêt pour la production, mais elle prévoit de continuer à faire évoluer CUDA Rust pendant 2027 et au-delà.

Les clés de CUDA Rust en 30 secondes

  • NVIDIA autorise l’écriture de kernels GPU en Rust, compilés en PTX, sans passer par CUDA C++.
  • Deux voies s’offrent : cuda-oxide pour la programmation SIMT à faible niveau et cutile-rs pour la gestion de blocs ou tiles.
  • NVIDIA recommande de débuter avec Tile lorsque la gestion fine des threads et de la mémoire n’est pas nécessaire.
  • Rust permet de transposer certaines garanties de propriété et d’aliasing à la programmation parallèle sur GPU.
  • Ces deux projets sont expérimentaux ; cuda-oxide est en phase early alpha.

Cette nouveauté règle une situation quelque peu étrange pour ceux qui construisent déjà une infrastructure d’intelligence artificielle en Rust. Le langage s’est progressivement intégré dans des composants systèmes, moteurs d’inférence et outils d’infrastructure, mais une fois arrivé au kernel qui s’exécute dans la GPU, il fallait souvent changer de langage.

Avec CUDA Rust, NVIDIA souhaite supprimer cette barrière.

Le kernel peut s’écrire en Rust et être directement converti en PTX (Parallel Thread Execution), la représentation intermédiaire utilisée par CUDA pour le code destiné aux GPU NVIDIA.

Cela ne signifie pas que Rust remplace immédiatement CUDA C++. NVIDIA décrit CUDA C++ et CUDA Python comme des outils matures pour l’entreprise, tandis que leurs deux alternatives pour Rust sont encore en phase initiale.

Deux modes différents pour programmer la GPU avec Rust

NVIDIA adapte à Rust ses deux modèles de programmation actuellement en développement dans CUDA.

Le premier est SIMT (Single Instruction, Multiple Threads), le modèle classique associé à CUDA, où le développeur décrit le comportement d’un thread, puis lance des milliers de threads en parallèle.

Ce mode correspond à cuda-oxide.

La seconde option, c’est Tile, une abstraction supérieure où le développeur définit des opérations sur des blocs de données, laissant au compilateur la décision de répartir le travail entre les threads physiques.

Ceci est géré par cutile-rs.

Caractéristique cuda-oxide cutile-rs
Modèle SIMT Tile
Niveau de contrôle Bas niveau Plus abstrait
Compilation Rust → MIR → Pliron → LLVM → PTX Rust → CUDA Tile IR
Rust Nightly fixé Stable 1.89 ou supérieur
CUDA 12.x ou plus récent CUDA 13.3
GPU minimal Compute Capability 8.0
LLVM intégré Oui / environnement dédié
État Early alpha
Recommandation NVIDIA Lorsque le contrôle précis est nécessaire

La recommandation de NVIDIA est claire : testez d’abord Tile, puis descendez à SIMT seulement si un contrôle précis des threads, mémoire ou architecture est indispensable.

C’est une approche différente du CUDA classique, où une grande partie de la performance dépendait de la compréhension fine de la répartition manuelle des blocs, threads et mémoire partagée.

CUDA Tile vise à déléguer davantage de ces décisions au compilateur.

L’avantage potentiel réside dans la portabilité entre générations de GPU. Si le code manipule un tile au lieu de gérer explicitement chaque thread, le compilateur a plus de flexibilité pour optimiser le kernel selon l’architecture ciblée.

cuda-oxide maintient le modèle classique de CUDA

Pour les développeurs requérant ce contrôle précis, cuda-oxide propose un backend personnalisé pour le compilateur rustc.

Lorsqu’une fonction est marquée comme kernel, le backend la traite via les représentations intermédiaires de Rust, le framework Pliron, et LLVM, pour générer du PTX. Le reste du code continue à utiliser le processus de compilation standard.

Une caractéristique clé est que le code d’hôte et le code destiné à la GPU peuvent coexister dans le même fichier Rust. Il n’est pas nécessaire de gérer deux projets séparés pour les kernels.

Le modèle reste compréhensible pour quiconque connaît CUDA :

#[kernel]
#[launch_bounds(256)]
pub fn vecadd(...) {
    let idx = thread::index_1d();
    // opération du thread
}

Chaque thread calcule son index et opère sur une partie des données.

Ce qui change, c’est comment Rust peut appliquer ses garanties de types et de propriété pour éviter certains défauts qui, avec CUDA traditionnel, ne se manifestaient qu’en exécution.

Par exemple, NVIDIA évoque DisjointSlice.

Un &mut [f32] classique représenterait un accès mutable à tout le slice, ce qui ne serait pas approprié pour des milliers de threads écrivant simultanément à différentes positions.

DisjointSlice divise cet accès pour que chaque thread dispose d’un droit exclusif sur sa position spécifique.

L’index du thread n’est pas simplement un entier arbitraire. thread::index_1d() retourne un type précis que l’on peut utiliser avec get_mut, et le résultat est une Option.

Cela permet de gérer explicitement les dépassements de limite, plutôt que de laisser le programme échouer par une erreur mémoire difficile à reproduire.

cuda-oxide introduit aussi des contrats de lancement.

Une annotation peut indiquer que le kernel attend des blocs de 256 threads et un domaine unidimensionnel. Avant de lancer le kernel, ces paramètres sont vérifiés par rapport à ces contrats et aux capacités réelles du matériel.

Un kernel sans contrat est marqué comme unsafe.

C’est un bon exemple des ambitions de NVIDIA pour intégrer la sécurité de Rust dans CUDA tout en gardant le contrôle du hardware.

cutile-rs laisse au compilateur la gestion des threads

cutile-rs adopte une philosophie radicalement différente.

Le développeur ne se concentre plus sur des threads individuels, mais sur des tiles de données.

Par exemple, si l’on a un vecteur de 1024 éléments divisé en blocs de 128, le système crée huit tiles, chacune étant une unité logique où le kernel s’exécute.

Une opération comme :

let z = api::zeros::(&[1024]).partition([128]);

ne se limite pas à diviser une structure de données. La partition définit quelles régions chaque tile peut modifier, précise la géométrie d’exécution et communique la taille au kernel.

À partir de là, le compilateur décide combien de threads physiques seront nécessaires pour exécuter cette opération sur la GPU.

La gestion de la mémoire mutable change aussi.

Chaque tile reçoit une région exclusive pour écrire. Deux tiles ne doivent pas pouvoir obtenir des références mutables en même temps sur la même partie de mémoire.

NVIDIA souhaite ainsi tirer parti de l’un des principes fondamentaux de Rust : s’il existe une référence mutable, aucune autre référence incompatible ne devrait exister sur ces données simultanément.

Ce principe est particulièrement pertinent pour la programmation sur GPU.

Les erreurs de concurrence sont souvent difficiles à reproduire, car des milliers de threads opèrent en ordre non contrôlé par le développeur. Un conflit mémoire peut n’apparaître que sous certaines charges ou configurations matérielles.

Le système de propriété de Rust peut anticiper certains de ces conflits avant même l’exécution.

Cela ne veut pas dire que Rust garantit automatique la sécurité de tous les kernels GPU. Par exemple, dans cuda-oxide, l’utilisation directe de mémoire partagée reste un contexte unsafe, un domaine où NVIDIA reconnaît qu’il reste du travail à faire.

Rust commence aussi à pénétrer les couches proches du GPU

Ce mouvement s’inscrit dans une tendance plus large.

NVIDIA rappelle que plusieurs composants de son infrastructure intègrent déjà Rust. NVIDIA Dynamo, sa plateforme d’inférence distribuée, possède un noyau en Rust, et NVTX fournit des bindings pour Rust. La société mentionne aussi le développement autour du contrôleur Nova pour Linux.

La programmation au niveau du kernel était, jusqu’ici, une étape nécessitant de changer de langage.

CUDA Rust aspire à faire communiquer ces deux mondes :

Application Rust → runtime CUDA → kernel Rust → PTX → GPU NVIDIA

Ce modèle est particulièrement pertinent pour les moteurs d’inférence, bases de données accelerées, calcul scientifique ou applications IA qui ont déjà adopté Rust dans leur infrastructure.

Il pourrait aussi réduire la complexité associée à la gestion de code Rust avec des kernels indépendants en CUDA C++.

NVIDIA ne considère pas encore CUDA Rust prêt pour la production

Ce lancement présente une limitation claire : ces projets ne remplacent pas encore CUDA C++ dans les applications critiques.

NVIDIA qualifie cuda-oxide d’early alpha. Il requiert Linux, une GPU avec Compute Capability 8.0 ou supérieure, CUDA 12.x, Clang, et une version spécifique de Rust Nightly.

L’installation reflète encore cet état :

cargo +nightly-2026-04-03 install --git https://github.com/NVlabs/cuda-oxide.git cargo-oxide

Il est ensuite possible de créer un projet avec :

cargo oxide new vecadd_demo
cargo oxide doctor
cargo oxide run

cutile-rs, lui, est un peu plus avancé du point de vue de la distribution. Il est publié en tant que package, fonctionne avec Rust stable, mais requiert CUDA 13.3.

cargo new vecadd_demo
cd vecadd_demo
cargo add cutile

NVIDIA indique aussi que cutile-rs est déjà utilisé hors de la société, notamment dans Grout, un moteur d’inférence de Hugging Face, et dans le projet mistral.rs.

Cependant, la prise en charge de CUDA reste incomplète et les interfaces peuvent évoluer.

Des travaux présentés dans Fearless Concurrency on the GPU donnent quelques indications sur les performances visées. Lors de tests publiés par leurs auteurs, cuTile Rust a atteint sur une NVIDIA B200 environ 7 Tb/s en opérations élément par élément et 2 PFLOPS en GEMM, soit environ 96 % des performances de cuBLAS. Ce sont des résultats expérimentaux sur des charges limitées, qui ne garantissent pas que tout kernel Rust atteindra automatiquement la vitesse des bibliothèques CUDA optimisées.

NVIDIA souhaite aussi améliorer l’interopérabilité entre CUDA Rust, CUDA C++ et CUDA Python. L’objectif est que choisir Rust pour un kernel ne signifie pas devoir porter le reste de l’application dans ce même langage.

En définitive, cette initiative va au-delà de la simple publication de deux nouvelles bibliothèques. NVIDIA ambitionne que Rust puisse couvrir toute la chaîne, de l’infrastructure système jusqu’au code exécuté par la GPU.

CUDA C++ restera sans doute la référence pour de nombreux développeurs pendant encore un certains temps. Mais si cuda-oxide et cutile-rs mûrissent comme prévu, Rust pourrait passer d’un langage de préparation et de lancement du travail GPU à celui qui l’écrit réellement.

Sources : developer.nvidia

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *