NVIDIA устраняет последнюю брешь в экосистеме Rust для GPU

70
NVIDIA устраняет последнюю брешь в экосистеме Rust для GPU

История взаимодействия Rust и видеоускорителей NVIDIA до недавнего времени напоминала сборку моста с двух берегов, которые так и не сошлись в середине. С одной стороны — зрелые enterprise-инструменты CUDA C++ и CUDA Python, с другой — всё более мощный пласт системного ПО для ИИ, написанный на Rust: драйвер Nova Linux, ядро NVIDIA Dynamo, биндинги NVTX. Всё это работало на хосте, но как только речь заходила о самом горячем участке — GPU-ядрах — разработчикам приходилось переключаться на C++ или использовать обёртки над чужеродным кодом.

Проблема была не в нежелании, а в фундаментальном несоответствии моделей памяти. Rust требует эксклюзивного доступа для изменяемых ссылок, а модель выполнения на GPU подразумевает тысячи потоков, одновременно обращающихся к одним и тем же буферам. Привычный &mut [f32] здесь не работает: компилятор справедливо отказывается выдавать одну изменяемую ссылку множеству потоков. Приходилось либо писать небезопасный код, либо уходить в C++.

В сентябре 2026 года NVIDIA анонсировала решение этой проблемы через два независимых направления. Первое — cuda-oxide — реализует привычную модель SIMT (Single Instruction Multiple Threads) нативно в компиляторе Rust. Это кастомный бэкенд для rustc, который перехватывает функции, помеченные атрибутом #[kernel], прогоняет их через MIR, затем через фреймворк Pliron и LLVM IR прямо в PTX — машинный код видеоускорителей. Всё остальное компилируется стандартным бэкендом. Для работы нужен Linux, GPU с вычислительной способностью 8.0 и выше, CUDA Toolkit 12.x, Clang с заголовками libclang и закреплённый nightly-тулчейн от 3 апреля 2026 года. Команда cargo oxide doctor проверяет окружение целиком.

Ключевая инновация здесь — типы, выражающие контракт параллелизма. DisjointSlice<T> разбивает единый изменяемый заимствование на пер-потоковые куски. thread::index_1d() возвращает не голый индекс, а типизированный маркер, который принимает только c.get_mut(idx). Выход за границы становится ветвлением Option, а не UB. Атрибут #[launch_contract] декларирует геометрию запуска, а prepare_vecadd валидирует конфигурацию против контракта и лимитов устройства, возвращая токен, который требует безопасный метод запуска. Без контракта доступен только unsafe-путь.

Второе направление — cutile-rs — поднимает абстракцию на уровень тайлов. Здесь программист описывает вычисления над подтензорами, а компилятор CUDA Tile IR сам решает, как отобразить их на потоки и блоки конкретной архитектуры. Ядро компилируется JIT при первом запуске, его AST встраивается в хост-бинарник макросом #[cutile::module]. Требования скромнее: CUDA 13.3, стабильный Rust 1.89+, Linux, GPU CC 8.0+. Никаких nightly и собственного LLVM. Пакет опубликован в crates.io, подключается через cargo add cutile.

В тайловой модели функция-вход выполняется один раз на тайл как единый логический поток. load_tile_like подтягивает соответствующие срезы входных тензоров, а z.store(tx + ty) записывает результат сразу по всему тайлу. Разбиение на тайлы .partition([128]) одновременно задаёт геометрию сетки, фиксирует размер тайла B и передаёт эксклюзивное владение подтензорами. Выполнение откладывается до .sync_on(&stream) — ленивость позволяет компилятору видеть весь граф операций.

Оба подхода — полноценные программы в одном файле, собираемые одной командой, без отдельных крейтов для ядер. NVIDIA заявляет о планах по межъязыковой интероперабельности: выбор модели и языка не запирает в изолированном сайло. CUDA Rust будет развиваться и зреть до 2027 года и дальше, закрывая последнюю брешь в стеке системного ПО для ИИ.

Последнее изменение:

0 Комментарии
Популярные
Новые Старые