Мануал по развёртыванию
Развернуть локальную LLM на Strix Halo (Ryzen AI Max+ 395): llama.cpp с нуля до первого ответа
Точный путь, которым мы разворачиваем на собственных коробках: настройка памяти, о которой молчит BIOS, запиненный контейнер llama.cpp на Vulkan и три проверки, что сервер действительно работает, — включая два отказа, которые прячутся за зелёными статусами.
- Платформа:
- Strix Halo (Ryzen AI Max+ 395)
- Время на прохождение:
- 45 мин
- Обновлено:
- 01.09.2026
Это путь развёртывания, который мы гоняем на собственных машинах с Ryzen AI Max+ 395 — тех же коробках, что стоят за нашими опубликованными цифрами. Без теории и каталога вариантов: один рабочий путь, с ловушками, размеченными там, где они ловили нас. Ожиданий по скорости здесь намеренно нет — они живут в отчётах, измеренные как положено.
Понадобятся: коробка на Strix Halo (любого вендора), Linux со свежим ядром, Docker и место на диске под выбранную модель.
Шаг 1 — сначала разберитесь с потолком памяти
На Linux ваши модели будут жить в GTT, а не в выделенном через BIOS куске VRAM, и потолок задаёт параметр ядра. Пропуск этого шага — самая частая причина, по которой большая модель отказывается грузиться на этом железе. Проверьте текущий лимит:
cat /sys/module/ttm/parameters/pages_limit
Умножьте на 4 KiB, чтобы получить байты. Если выходит лишь доля вашей
RAM — поднимите через командную строку ядра (ttm.pages_limit=...) и
перезагрузитесь. Полное объяснение, почему ползунок в BIOS не тот рычаг, —
с показаниями нашей обслуживающей ноды — в
отчёте про распределение памяти.
Кусок в BIOS оставьте маленьким.
Шаг 2 — возьмите модель
Выберите GGUF-артефакт и запишите его точную ревизию. MoE класса 35B в Q4_K_M — та золотая середина, которую мы ежедневно обслуживаем на этом железе: остаётся место под контекст и вторую модель. Какой квант брать — вопрос измеренный; короткая версия: начните с Q4_K_M, а не с самого большого файла, который влезает.
mkdir -p /var/lib/llm/models
# скачайте выбранный .gguf сюда и запишите, ОТКУДА он взялся —
# репозиторий и ревизию. "main" переезжает; ваши записи — нет.
Шаг 3 — запустите сервер и запините его
Vulkan-сборка сервера llama.cpp работает на этом iGPU сразу:
docker run -d --name llm-server \
--device /dev/dri --device /dev/kfd \
-v /var/lib/llm/models:/models \
-p 8080:8080 \
ghcr.io/ggml-org/llama.cpp:server-vulkan \
-m /models/YOUR-MODEL.gguf \
-ngl 999 -fa on -c 32768 \
--host 0.0.0.0 --port 8080 --jinja
Две привычки, которые спасут вас позже. Первая: когда всё заработает,
вытяните образ заново по digest (ghcr.io/ggml-org/llama.cpp@sha256:...)
вместо тега — теги переезжают, и когда будущее обновление изменит
поведение, вам нужно будет знать, на какой именно сборке вы были. Вторая: если
меняете --port, знайте, что встроенный healthcheck образа всё равно
стучится в 8080 — контейнер будет показывать unhealthy, безупречно
обслуживая запросы. Мы разобрали
ровно эту ловушку после
того, как она укусила нас, — либо держите внутренний порт на 8080, либо
переопределите healthcheck.
Шаг 4 — спросите сервер, что он на самом деле запускает
Не доверяйте своей командной строке; доверяйте процессу:
curl -s localhost:8080/props | python3 -m json.tool | head -40
Прочитайте n_ctx, путь к модели и число слотов. Дефолты меняются между
версиями llama.cpp, а флаг, который вы не выставили, всё равно часть вашей
конфигурации — этот урок обошёлся нам дорого.
Шаг 5 — smoke-тест, который действительно что-то доказывает
HTTP 200 пока не доказывает ничего. Отправьте настоящий запрос и проверьте три вещи:
curl -s localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"Reply with one short sentence: what is inference?"}],
"max_tokens":400,"temperature":0}' \
| python3 -c "import json,sys; d=json.load(sys.stdin); m=d['choices'][0]['message']; \
print('content:', repr(m.get('content','')[:120])); \
print('finish:', d['choices'][0].get('finish_reason')); \
print('tokens:', d.get('usage',{}).get('completion_tokens'))"
Проверка один: content не пуст. Рассуждающая модель может сжечь
весь бюджет токенов на размышления и вернуть пустой ответ под безупречным
HTTP 200 — мы измерили, как часто;
если видите такое — поднимите max_tokens или отключите размышления.
Проверка два: finish — это stop, а не length. Проверка три: если
когда-нибудь будете что-то измерять, считайте токены из
usage.completion_tokens — никогда из числа событий стрима.
Шаг 6 — решите про режим размышлений
Если у вашей модели есть режим размышлений, решите осознанно, остаётся ли он включённым. Для повседневного чата и структурной автоматизации на этом железе мы измерили, во что он обходится и что даёт взамен, — прочитайте это до того, как отдавать дефолт своим пользователям.
Куда дальше
- Выбор бэкенда: Vulkan — наш серверный дефолт на этом железе; сравнение с ROCm показывает, что даёт каждый.
- Больше пользователей: прежде чем обещать коробку команде, прочитайте лестницу конкурентности.
- Проверьте собственные цифры: ворклоады за нашими отчётами открыты — прогоните их на свежем сервере и сверьтесь с нашими клеймами.