PyTorch на ARM-серверах: почему pip install torch молча ломал GPU и как это починили

PyTorch на ARM-серверах: почему pip install torch молча ломал GPU и как это починили

Вы заказываете сервер с NVIDIA GH200, стоимостью больше вашей квартиры, запускаете стандартную команду pip install torch и получаете CPU-only сборку. PyTorch устанавливается без ошибок, зависимости разрешаются, всё выглядит нормально — но torch.cuda.is_available() возвращает False. GPU есть, драйверы стоят, а фреймворк его не видит. Причина оказывается настолько банальной, что хочется смеяться сквозь слёзы: в PyPI для Linux aarch64 просто не было CUDA-enabled wheel. Два года сообщество обходило это костылями, пока весной 2026-го фикс наконец не дошёл до stable-релиза.

В статье на PyTorch Blog инженер Inferact и участник Technical Advisory Committee PyTorch Foundation Кайчао Ю рассказывает, как одна упаковочная проблема превращала пятиминутную установку в полдня дебага, какие workaround'ы придумывала команда vLLM и почему исправление в PyTorch 2.11 важнее, чем кажется на первый взгляд.

Почему pip install torch ломался на ARM-серверах

Проблема начинается с архитектуры. PyTorch публикует CUDA-enabled wheels в собственный индекс download.pytorch.org, а в основной PyPI — только CPU-сборки. На x86_64 это не мешает: pip по умолчанию ищет в PyPI, не находит GPU-версию, но пользователи привыкли добавлять --index-url и забирать нужную сборку из правильного индекса. На aarch64 Linux ситуация была хуже — GPU wheel вообще отсутствовал в PyPI, и даже с кастомным индексом установка превращалась в ловушку.

Ловушка работала через транзитивные зависимости. PyPI не позволяет пакету указывать кастомный индекс для своих зависимостей. Если в дереве зависимостей vLLM какой-либо пакет объявлял требование torch с версией, не совпадающей с установленной, pip молча возвращался к дефолтному PyPI, находил там CPU-only wheel, удалял вашу аккуратно установленную CUDA-сборку и ставил процессорную. Никаких предупреждений. Установка завершалась успешно, но GPU исчезал.

Для разработчика на GH200 или GB200 это означало, что однострочная установка vLLM превращалась в лабиринт из --extra-index-url, закреплённых версий и постинсталляционных проверок. Ты думаешь, что всё работает, запускаешь модель — и получаешь ошибку CUDA not available. Потом полдня тратишь на то, чтобы понять, что pip подменил твой torch, потому что какая-то транзитивная зависимость потребовала другую версию.

Как vLLM обходил проблему годами

Пока upstream-фикс созревал, команда vLLM не могла позволить себе ждать. Пользователи Grace Hopper и Grace Blackwell систем ставили фреймворк, ловили баг и уходили разочарованными. Первый workaround появился в сентябре 2024-го — скрипт use_existing_torch.py, который буквально переписывал зависимости vLLM на лету.

Логика была простая и грубая: ты сам ставишь правильный torch из нужного индекса, затем запускаешь скрипт, который вычищает все упоминания torch, torchvision и torchaudio из pyproject.toml, setup.py и requirements. Без этих пинов pip больше не может "помочь" и подменить твою сборку. Это уродливо — фреймворк переписывает собственные зависимости во время установки — но это работало. Более года GH200-пользователи обходились этим костылём.

Второй workaround появился позже, когда uv созрёл как альтернатива pip. В pyproject.toml vLLM добавили строчку no-build-isolation-package = ["torch"]. Это говорит uv не собирать torch в изолированном окружении, а reuse уже установленную версию из текущего окружения. В сочетании с предварительной установкой правильного torch это давало более элегантный путь: одна строка в конфиге вместо переписывания файлов. Но оба workaround'а имели общий недостаток — они требовали от пользователя знать о проблеме заранее. Новый разработчик на GB200, который просто следовал стандартной инструкции, всё равно попадал в ловушку.

Путь от хакатона до TAC: как фикс попал в релиз

История началась в октябре 2024-го на хакатоне CUDA MODE. Кайчао Ю пытался запустить vLLM на GH200, потратил полдня на дебаг и понял, что корень проблемы не в коде, а в упаковке. Он зафиксировал issue в PyTorch, но одиночный багрепорт не меняет инфраструктуру крупного проекта.

Поворот случился, когда vLLM вступила в PyTorch Foundation, а Кайчао стал представителем проекта в Technical Advisory Committee. TAC — это не церемониальный орган, а площадка, где downstream-проекты могут доносить боли до людей, способных их исправить. В августе 2025-го он завёл формальный трекер pytorch/pytorch#160162, а в январе 2026-го поднял вопрос прямо на TAC-встрече от имени пользователей vLLM.

Запрос был простым: публиковать aarch64 GPU wheels в дефолтный PyPI, чтобы pip install torch "просто работал" на GB200-классных машинах, как это работает на x86. NVIDIA-инженеры поддержали инициативу и предложили подход small wheel — динамически линковаться с библиотеками вроде NCCL и cuBLAS вместо статической линковки. Это не раздувает размер wheel до неприличных значений и укладывается в ограничения PyPI, которые активно дискуражат тяжёлые бинарники.

В апреле 2026-го на очередном TAC Кайчао узнал, что фикс вошёл в PyTorch 2.11.0. Пиотр Бялецкий из NVIDIA подтвердил, что изменение живое в релизе. Проверка на GB200 показала именно то, что нужно: скучный, предсказуемый результат. Одна строка в терминале, и весь стек workaround'ов становится ненужным.

Что изменилось в PyTorch 2.11 и почему это важно

С точки зрения кода — ничего революционного. С точки зрения опыта разработчика — всё. Раньше установка на aarch64 требовала знания трёх вещей: кастомного индекса PyTorch, опции --extra-index-url и опасности транзитивных зависимостей. Теперь достаточно стандартной команды, которая работает и на x86, и на ARM.

Для vLLM это означает, что новый пользователь с Grace Blackwell больше не проходит через сценарий "установил, не работает, дебажу полдня". Стандартные инструкции теперь применимы к aarch64 без оговорок. Workaround'ы — use_existing_torch.py и no-build-isolation — остаются в кодовой базе, но их роль меняется. Они по-прежнему полезны для продвинутых пользователей, которые собирают PyTorch из исходников или используют nightly-сборки, но больше не являются налогом на каждого новичка.

Более широкий контекст — это экосистемное сотрудничество под крышей PyTorch Foundation. Проблема прошла полный путь: от разработчика, ругающегося в терминал на хакатоне, через TAC-дискуссию, формальный трекер, релиз-инженеринг и финальную публикацию wheels. Foundation сделал этот путь коротким. Без общей площадки vLLM и PyTorch решали бы проблему независимо, и фикс мог бы откладываться ещё годами.

Почему aarch64 становится критичной архитектурой для AI

Grace Hopper и Grace Blackwell — не нишевые эксперименты. GH200 объединяет 72-ядерный ARM-процессор Grace с GPU Hopper через NVLink-C2C, давая единую память и пропускную способность, недостижимую в традиционных x86-сборках. GB200 и GB300 идут дальше — два GPU на один CPU, масштабируемые до кластеров из тысяч чипов. NVIDIA ставит на ARM как на фундаментальную платформу для дата-центров, а не только для мобильных устройств.

Когда архитектура становится массовой, инфраструктурные детали вроде упаковки Python-пакетов превращаются в стратегические препятствия. Каждый час, который разработчик тратит на --index-url вместо обучения модели, — это замедление всей индустрии. PyTorch 2.11 убирает одно такое препятствие, и его значение трудно переоценить, хотя в release notes это выглядит как скромная строчка про packaging.

Часто задаваемые вопросы

Мне нужно что-то менять в существующем проекте на GB200?

Нет. Если у вас уже работающая установка с кастомным индексом — она продолжит работать. Переход на PyTorch 2.11 упрощает только новые установки и убирает необходимость в workaround'ах.

Почему нельзя было просто добавить wheel в PyPI раньше?

PyPI активно дискуражит большие бинарные пакеты из-за затрат на хостинг и скачивание. Решение — small wheel с динамической линковкой к CUDA-библиотекам — требовало координации между PyTorch core team, NVIDIA и инфраструктурой PyPI. Это заняло время, но дало устойчивое решение.

Работает ли это только для vLLM?

Нет. Любой проект, зависящий от PyTorch на aarch64 Linux — Hugging Face Transformers, DeepSpeed, Axolotl, ComfyUI — получает тот же эффект. vLLM просто была на передовой, потому что inference на GB200 — один из первых массовых сценариев использования.

Итог

PyTorch 2.11 не добавляет новых операторов, не ускоряет backward pass и не ломает совместимость. Он делает кое-что более ценное — убирает невидимый барьер для разработчиков на ARM-серверах. Два года сообщество платило налог в виде костылей, переписывания зависимостей и дебага чужих ошибок упаковки. Теперь pip install torch на GH200 и GB200 работает так же предсказуемо, как на любом x86-сервере. Мелочь, которая меняет всё.

← Все записи