В начале было слово — и слово было «нельзя»
Когда мне поставили задачу: «Запусти DeepSeek-R1 на нашем новом ARM64-сервере с A100, всё в закрытом контуре, без интернета», я хмыкнул. Ну, подумаешь, ARM64 — не x86, подумаешь, драйверы NVIDIA под эту архитектуру — как иголка в стоге сена. А ещё надо, чтобы всё работало в изолированной сети, без apt, pip install и прочих радостей жизни. Спойлер: я справился. И сейчас расскажу, как не сойти с ума и не спалить сервер.
Это не очередной «возьми ChatGPT и оберни в FastAPI». Это хардкорный опыт интеграции LLM с импортозамещённым железом, где каждый шаг — борьба. Если вы тоже хотите запустить DeepSeek-R1 на чём-то, кроме Intel Xeon, — вы по адресу.
Почему DeepSeek-R1, а не V4?
На дворе 2026-й, уже вышли DeepSeek-V4 Flash и Pro с 1.6 триллиона параметров, но для работы в закрытом контуре R1 остаётся золотым стандартом. Модель с открытыми весами, дистиллированные варианты до 70B, которых хватает для большинства задач — от генерации документов до RAG. V3.2 локально тоже неплох, но R1 даёт лучшие результаты на цепях рассуждений. А главное — у нас уже были веса, скачанные до изоляции сети. Всё серьёзно.
Железо, которое мы имеем
- CPU: Baikal-M (8 ядер ARM Cortex-A75, 2.0 ГГц) — первый блин, но комом. Память DDR4-3200, 64 ГБ (два канала).
- GPU: NVIDIA A100 80 ГБ — единственное, что не требует импортозамещения, но встроить в ARM64-систему — квест.
- ОС: Ubuntu 22.04 для ARM64 (офлайн-образ).
Важно: Не все отечественные ARM64 процессоры одинаково полезны. Baikal-M имеет всего 8 ядер и слабый нейронный блок — инференс LLM целиком ляжет на GPU. Baikal-S (48 ядер) уже интереснее, но у нас его не было. Если у вас Skif или YADRO — подход тот же, но следите за версией ARMv8.x (A100 требует ARMv8.2+).
Шаг 1: Добыть драйвер NVIDIA для ARM64 (офлайн-головоломка)
Звучит просто: «установи драйвер». Но NVIDIA официально поддерживает серверные ARM64 (Ampere Altra, AWS Graviton) через Universal Driver. На июнь 2026 актуальна ветка 570 (или 565 LTS). Проблема: в закрытом контуре нет доступа к официальному репозиторию.
Что я сделал:
- Скачал
NVIDIA-Linux-aarch64-570.xx.xx.runна машине с интернетом, записал на USB. - Установил зависимости:
build-essential, dkms, libc6-dev— их тоже пришлось тащить через apt-offline. - Запустил
sh ./NVIDIA-*.run --accept-license --no-questions— и тут секрет: Secure Boot на Baikal-M отключен, иначе пришлось бы подписывать модуль.
После установки команда nvidia-smi должна показать A100. Если нет — проверьте, что в BIOS включена поддержка PCIe Gen4 и Resizable BAR (для A100 это критично). На Baikal-M с этим были танцы с бубном — пришлось прошивать микрокод, но это отдельная история.
Шаг 2: CUDA Toolkit и библиотеки для ARM64
NVIDIA выпускает CUDA Toolkit для ARM64 под названием «CUDA for Arm64 Server». Нужна версия 12.x (на 2026 год актуальна 12.6). Скачиваем локальный .run-инсталлятор. Устанавливаем в /usr/local/cuda.
Лайфхак: Если не хотите ставить полный тулкит, достаточно cuda-cccl, cuda-cudart, cuda-cublas для компиляции llama.cpp. Экономит 2 ГБ на флешке.
Шаг 3: Сборка llama.cpp под ARM64 с поддержкой CUDA
llama.cpp — наше всё. Он умеет работать с ARM64 и CUDA, но требует правильных флагов. Вот как собирать:
git clone https://github.com/ggml-org/llama.cpp.git
cd llama.cpp
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release \
-DLLAMA_CUDA=ON \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++ \
-DCUDAToolkit_ROOT=/usr/local/cuda
make -j$(nproc)Грабли: ARM64-компилятор GCC (по умолчанию 11.4) иногда выдаёт ошибки на флагах оптимизации -march=armv8.2-a+fp16+rcpc+dotprod. Я добавил их вручную в CMakeLists.txt. Если у вас Baikal-M (A75), лучшее, что можно выжать — с FP16 и DOTPROD. Для больших матриц это даёт прирост 20-30%.
«Без этих флагов библиотека падала с сегфолтом на первом же вызове cuBLAS — потратил день на дебаг. Не повторяйте.»
Шаг 4: Где взять модель DeepSeek-R1?
Оригинальная R1 (671B) не влезет ни в одну A100, даже с 80 ГБ. Даже 4-bit потребует около 400 ГБ. Поэтому мы используем дистиллированную версию: DeepSeek-R1-Distill-Llama-70B. В формате GGUF (Q4_K_M) она весит ~40 ГБ. При контексте 32K это идеально для A100.
Веса нужно заранее скачать с Hugging Face (в офлайн — перенести на SSD). Я рекомендую TheBloke/DeepSeek-R1-Distill-Llama-70B-GGUF — файл deepseek-r1-distill-llama-70b.Q4_K_M.gguf.
Шаг 5: Запуск inference — тест-драйв
Собранный llama.cpp поставляется с утилитой llama-server. Запускаем:
./llama-server -m /path/to/deepseek-r1-distill-llama-70b.Q4_K_M.gguf \
--n-gpu-layers 99 \
--ctx-size 32768 \
--host 0.0.0.0 --port 8080Параметр --n-gpu-layers 99 отправляет все 80 слоёв модели на GPU. На Baikal-M CPU не успевает обрабатывать даже префилл — только GPU справляется.
После запуска делаем запрос через curl:
curl -X POST http://localhost:8080/completion \
-H "Content-Type: application/json" \
-d '{"prompt": "Рассмотри в задаче...", "n_predict": 256}'На A100 80 ГБ получаем ~25 токенов/сек (генерация) — не рекорд, но для дистиллированной модели в закрытом контуре более чем достойно. Сравните с 85 токенами на V4-Flash с RTX PRO 6000 — да, есть куда расти, но тут другая архитектура и железо.
Типичные ошибки и как их обойти
Ошибка 1: ‘CUDA error: no kernel image is available for execution on the device’
Это значит, что собранная библиотека не содержит PTX для вашей архитектуры. Решение: при cmake указать -DLLAMA_CUDA_FORCE_ARCH=80 (A100 — архитектура sm_80). При сборке для Ampere Altar см. спецификацию.
Ошибка 2: ‘Could not load library libcuda.so.1’
Драйвер не подхватился. Проверьте /etc/ld.so.conf.d/nvidia.conf и запустите ldconfig. На Baikal-M пути отличаются — я прописал вручную.
Ошибка 3: Медленный инференс — 5 токенов/сек
Скорее всего, часть слоёв ушла на CPU. Используйте --n-gpu-layers 99. Если не хватает памяти GPU — уменьшайте контекст или используйте K-quant (Q4_K_M).
Безопасность в закрытом контуре: что ещё проверить
Наша система изолирована физически, но есть нюансы:
- llama-server по умолчанию слушает на всех интерфейсах — привяжите к
127.0.0.1или используйте systemd socket activation. - Модель уже лежит на SSD — сделайте checksum (SHA256) перед развёртыванием, чтобы исключить повреждение при переносе.
- Отключите Swap на сервере — A100 любит прямой доступ к памяти, а подкачка на ARM64 убьёт производительность.
Можно ли было проще? (Спойлер: нет)
Собрать всё это на отечественном ARM64 — извращение, но оно того стоит, если задача — полное импортозамещение. На практике из-за ограничений Baikal-M (8 ядер, два канала памяти) вы не получите больше 30 токенов/сек даже на A100. Threadripper с x86 даёт в 2-3 раза больше, но это не наш случай.
Если у вас есть доступ к Baikal-S или YADRO-серверам с большим числом ядер и нормальной памятью — результаты будут лучше. И не забывайте про DeepGEMM: если вы используете vLLM (не под ARM64), можно выжать больше. Но для закрытого контура vLLM — это лишняя зависимость.
Мой совет: если можете выбрать железо — возьмите Ampere Altra (ARM64 серверный) или обычный x86. Но если стоит задача «только наше», то вооружитесь этой инструкцией, терпением и парой литров кофе.
И помните: в закрытом контуре живут не только драконы, но и вполне работоспособные LLM.