NVIDIA представляє CUDA Rust із cuda-oxide (SIMT) і cutile-rs (Tile) для безпечних під час компіляції GPU-ядер
NVIDIA анонсувала CUDA Rust — ініціативу, покликану зробити Rust повноцінною мовою для написання ядер GPU. Код Rust уже міг запускати ядра CUDA, але тіло ядра зазвичай доводилося писати в іншому середовищі. CUDA Rust усуває цю прогалину за допомогою двох проєктів NVlabs з відкритим кодом: cuda-oxide для моделі SIMT і cutile-rs для новішої моделі Tile. Обидва нативно компілюють ядра Rust і використовують правила володіння Rust, щоб відхиляти помилки псевдонімізації під час компіляції.
Чи можна це розгортати? Частково. cutile-rs опубліковано на crates.io, він працює зі стабільною версією Rust 1.89+ і вже використовується в рушії інференсу Grout від Hugging Face та в mistral.rs. cuda-oxide перебуває на ранній альфа-стадії. Обидва проєкти перебувають в альфа-фазі, і їхня готовність до використання у виробництві не підтверджена.
Чому Rust для ядра GPU
Системний рівень ШІ — від рушіїв інференсу до драйверів і середовищ виконання агентів — дедалі частіше пишуть на Rust. Драйвер NVIDIA Nova для Linux написаний на Rust, NVIDIA Dynamo має ядро на Rust, а NVTX має прив’язки до Rust. Ядро GPU було винятком.
Два напрямки відповідають двом моделям програмування, які вже пропонує CUDA. SIMT — це модель, що використовується в CUDA C++ і numba-cuda: ви описуєте, що робить один потік, і запускаєте тисячі таких потоків. Tile — новіша модель, також доступна в C++ і Python: ви описуєте, що робить один фрагмент даних, а компілятор Tile IR бере на себе відображення потоків і структуру розміщення в пам’яті. NVIDIA рекомендує спочатку використовувати Tile, а SIMT — для явного контролю потоків і пам’яті. Запланована взаємодія між мовами означає, що вибір Rust не позбавить розробників можливості використовувати C++ або Python.
Напрямок SIMT: cuda-oxide
cuda-oxide — це спеціальний бекенд генерації коду rustc. Він спрямовує функції #[kernel] через MIR Rust, фреймворк IR спільноти Pliron і LLVM IR до PTX, а все інше передає стандартному бекенду. NVIDIA створила діалекти GPU поверх Pliron.
Вимоги: Linux, GPU з обчислювальною спроможністю 8.0 або новішою, CUDA 12.x або новіша, clang із libclang і зафіксований нічний ланцюжок інструментів (nightly-2026-04-03). cargo oxide doctor перевіряє налаштування, а cargo oxide new створює каркас програми додавання векторів, де код хоста й пристрою міститься в одному файлі.
Обґрунтування безпеки полягає в сигнатурі ядра. Входи a і b — це звичайні спільні зрізи. Вихід c — це DisjointSlice<f32>, тип, який надає кожному потоку ексклюзивний доступ до власного елемента. Звичайний &mut [f32] вимагав би, щоб кожен потік утримував те саме змінюване запозичення, що Rust забороняє. c.get_mut(idx) повертає Option, тому вихід за межі перетворюється на оброблювану гілку. Атрибут #[launch_contract] оголошує форму блока, а згенерований метод prepare_vecadd перевіряє конфігурацію запуску на відповідність їй перед виконанням безпечного запуску.
Напрямок Tile: cutile-rs
cutile-rs працює на рівень вище. Кожен блок фрагментів виконує тіло ядра один раз як один логічний потік над одним підтензором, а компілятор визначає, скільки реальних потоків GPU його підтримуватимуть. Макрос #[cutile::module] вбудовує AST ядра у двійковий файл хоста та JIT-компілює його через CUDA Tile IR під час першого запуску ядра.
Вимоги простіші: обчислювальна спроможність 8.0 або новіша, CUDA 13.3, стабільна версія Rust 1.89 або новіша та Linux; нічна версія й спеціальний LLVM не потрібні. Налаштування складається з виконання cargo new, а потім cargo add cutile.
Виклик .partition([128]) на стороні хоста виконує 3 завдання. Він надає кожному фрагменту ексклюзивне володіння його частиною зі 128 елементів, фіксує сітку на рівні 1 024 / 128 = 8 фрагментів і задає константну ширину фрагмента B. Вхідні тензори використовують -1 як динамічний вимір, що визначається під час запуску. Згенерований засіб запуску перебирає у володіння всі тензори й повертає їх після завершення роботи GPU. Нічого не виконується до .sync_on(&stream); усе до цього моменту є лінивим описом, записаним в одному ланцюжку.
Що виявляє компілятор
Передавання вихідного буфера ядра SIMT як одного з його власних входів завершується помилкою error[E0502]: cannot borrow c_dev as mutable because it is also borrowed as immutable. Така сама псевдонімізація на стороні Tile завершується помилкою error[E0382]: use of moved value: z. cuda-oxide перевіряє кожен виклик запуску; система володіння cutile-rs поширюється на тензори через межу запуску, що NVIDIA називає сильнішою гарантією.
Tile не надає доступу до спільної пам’яті або індексації потоків, якими можна було б неправильно скористатися. SIMT зберігає цей контроль, але спільна пам’ять у cuda-oxide наразі потребує unsafe.
Основні висновки
- CUDA Rust додає 2 нативні напрямки ядер GPU у Rust: cuda-oxide (SIMT) і cutile-rs (Tile).
- cuda-oxide компілює MIR Rust через Pliron і LLVM у PTX; для нього потрібна зафіксована нічна версія.
- cutile-rs працює зі стабільною версією Rust 1.89+ і CUDA 13.3 та виконує JIT-компіляцію через CUDA Tile IR.
- Обидва проєкти відхиляють псевдонімізацію буферів під час компіляції за допомогою перевірки запозичень і системи володіння Rust.
- cutile-rs уже використовується в Grout і mistral.rs; жоден із проєктів поки не готовий до використання у виробництві.
Ознайомтеся з технічними деталями тут. Також підписуйтеся на нас у Twitter і не забудьте приєднатися до нашого сабреддіту про машинне навчання зі 150 тис.+ учасників та підписатися на нашу розсилку. Стривайте! Ви користуєтеся Telegram? тепер ви також можете приєднатися до нас у Telegram.
Потрібно налагодити партнерство з нами для просування вашого репозиторію GitHub, сторінки Hugging Face, релізу продукту, вебінару тощо? Зв’яжіться з нами
Перекладено автоматично з англійської. Оригінал статті — за посиланням нижче.