PunchSoldiers rescue three abducted victims in KebbiThe Jerusalem PostWith two days until election: Eisenkot leads over Netanyahu, but neither can reach majority - pollInquirerLacson: Use ‘savings’ from Senate budget cuts for El Niño preparationsCNN TürkTütün ürünü kullanımına yeni düzenleme: Açık alanlarda sınırlanacak한겨레아파트서 부부싸움 중 방화 50대…긴급체포20 MinutenLindt-Präsident: «Tut weh, die Produkte im Ausverkauf zu sehen»ZDF heuteEntdecken Sie das ZDF-Nachrichtenstudioالنهارالجيش الإيراني يسقط مسيّرة أميركية في بندر عباس... عراقجي: الهجوم مجدّداً علينا لن يُحقّق نتائج مختلفةCapital FMRuto Praises Kalonzo for Recognising Govt Development Record in Ukambani경향신문트럼프 행정부, ‘알래스카 결과 확정 보류’ 소송···선거 막판 ‘부패 스캔들’ 변수될까Het Laatste Nieuws“Hij moet zijn tijd nemen”: ook collega-trainers leven mee met Vincent KompanyMintFrom France to Italy, what protests mean for Europe’s $187 bn winter tourism industry ahead of Christmas-New Year season
The Daily Newsstand · Free, Always
Sunday, October 25, 2026

Локальный LLM-сервер на AMD Strix Halo: запуск Qwen3.8-Flash-Next через HALOGEN в Fedora 43

Translate

Ещё недавно «запустить LLM у себя» почти всегда означало одно: discrete GPU с парой десятков гигабайт VRAM. AMD Strix Halo с 128 ГБ унифицированной памяти эту привычку ломает — крупные MoE-модели на нём заводятся спокойно, если inference-движок умеет работать с общей памятью, memory mapping и своеобразием встроенной графики.

Ниже — практическая настройка Qwen3.8-Flash-Next на Fedora 43 Server через HALOGEN: OpenAI-совместимый API, ключ, четыре параллельные сессии и доступ снаружи через порт 9091.

Что за зверь Qwen3.8-Flash-Next

Это не «обычная» модель даже по меркам MoE. Внутри — смесь экспертов (MoE), гибридное внимание и отдельные N-gram embeddings. Если коротко:

Параметр

Значение

Основная модель

125 млрд параметров

Активируется на токен

около 6 млрд параметров

N-gram embedding table

около 51 млрд параметров

MTP-head

около 4 млрд параметров

Количество слоёв

48

MoE-экспертов

512 routed + 1 shared

Активных routed-экспертов

10

Нативный контекст

262 144 токена

Максимальный расширенный контекст

до 1 000 000 токенов

Возможности

текст и опционально изображения

В чём фокус MoE: суммарная ёмкость модели огромная, но на каждом токене она считает лишь малую часть весов. Поэтому и получается скорость выше, чем у плотной модели такого же полного размера.

Почему HALOGEN, а не llama.cpp

У Strix Halo unified memory architecture: CPU и встроенный GPU делят одну LPDDR5X-память. Отдельной физической VRAM, как у дискретных NVIDIA или Radeon, здесь просто нет.

HALOGEN рассчитан именно на такое устройство:

  • заточен под GPU gfx1151;

  • хранит веса в собственном формате .hgn;

  • не пытается копировать весь комплект весов в «VRAM»;

  • держит N-gram lookup table через memory mapping;

  • ускоряет генерацию с помощью MTP/speculative decoding;

  • отдаёт наружу OpenAI-совместимый HTTP API.

Это не универсальная замена llama.cpp или vLLM — все его преимущества вытекают из узкой заточки под одну архитектуру GPU и одну линейку моделей.

И сразу важный момент про BIOS: параметр UMA Frame Buffer выставляйте в минимальное фиксированное значение, а не оставляйте Auto. HALOGEN нужен доступ к обычной памяти хоста, а большой статический резерв под iGPU только съедает доступную RAM.

Сколько места нужно на диске

Стандартный набор весов HALOGEN выглядит так:

Файл

Размер

Назначение

qwen38-flash-next-v2.hgn

62,1 GiB

Основной checkpoint

qwen38-flash-next-ngram.hgn

47,7 GiB

N-gram lookup table

tokenizer/

небольшой

Токенизатор

Всего

около 110 GiB

Текстовая модель

qwen38-flash-next-vision.hgn

0,84 GiB

Опциональная поддержка изображений

qwen38-flash-next-mtp.hgn

1,42 GiB

Draft-head для стороннего GGUF

При первом запуске HALOGEN сам скачает нужные файлы, если передать ему:

-e HALOGEN_DOWNLOAD=peonist-ai/halogen-qwen3.8-flash-next

Свободного места закладывайте не меньше 120–140 ГБ: помимо самих весов понадобятся служебные файлы и запас под обновления.

Какую скорость ждать

По опубликованным результатам HALOGEN на Strix Halo ориентиры такие:

Сценарий

Производительность

Генерация текста

около 54 токенов/с

Благоприятный сценарий speculative decoding

до 94 токенов/с

Генерация при редактировании кода

до 81 токена/с

Генерация tool calls

около 71 токена/с

Prefill: промпт 8K токенов

около 1 821 токена/с

Prefill: промпт 32K токенов

около 1 740 токенов/с

Prefill: промпт 131K токенов

около 1 675 токенов/с

Что это значит на практике? Новый документ на 32K токенов обработается примерно за 19 секунд. Уже закэшированная история диалога продолжится заметно быстрее. Ответ на 1 000 токенов при 54 токенах/с будет крутиться секунд 18–19. А реальная скорость, конечно, зависит от текста, длины контекста, температуры, speculative decoding и того, что ещё грузит машину параллельно.

При четырёх одновременных сессиях HALOGEN просто делит вычислительный ресурс между потоками. Ориентир из документации: примерно 76 токенов/с суммарно и 11–19 токенов/с на поток. Так что четыре слота полезны для API-сервера с несколькими клиентами, но единичный запрос они не ускоряют.

Синтетические тесты: проверяем на живом сервере

Цифры из readme — это хорошо, но интереснее погонять бенчмарк по реальному эндпоинту. Подошёл LLMPerf от ray-project: он собирает промпты из случайных кусков Шекспира и меряет по каждому запросу время до первого токена (TTFT) и интервалы между токенами (ITL) — из них легко получить скорость чтения и записи.

По ходу дела выяснились две грабли, о которых стоит знать заранее:

  • SSE-парсер llmperf пришлось патчить. На длинных контекстах при c=4 стрим молчит достаточно долго, и прокси начинает слать keep-alive (:ping), от которых наивный парсер падает. Лечится просто: игнорировать комментарии, разбирать только строки data:.

  • Модель — reasoning-модель. Она «размышляет» перед ответом (поле reasoning_content), и эти паузы искажают метрики: на 128k свободная генерация показывала жалкие 2.6 ток/с записи. Отключается штатным для Qwen3 параметром chat_template_kwargs: {"enable_thinking": false}, а чтобы модель не останавливалась по EOS после пары сотен токенов, добавляли ignore_eos: true.

Финальная серия — reasoning OFF, один поток, выход = 1/10 контекста, 12 запросов без единой ошибки:

Контекст

Выход (факт)

TTFT p50

Чтение

Запись

E2E p50

8k

888

4.2 с

1 965 ток/с

96.4 ток/с

13.3 с

16k

1 775

8.1 с

2 040 ток/с

98.1 ток/с

26.6 с

32k

3 571

16.1 с

2 048 ток/с

96.5 ток/с

53.4 с

64k

7 203

32.3 с

2 035 ток/с

96.5 ток/с

121 с

128k

14 518

66.0 с

1 992 ток/с

94.5 ток/с

230 с

Что из этого следует:

  • Запись — константа ~95–98 ток/с на всём диапазоне контекстов. «Деградации от длины контекста» не существует — её имитировали паузы размышлений (разница до 36×). И обещанные до 94 токенов/с в благоприятном сценарии — не маркетинг: форсированный стрим стабильно выдаёт ~96.

  • Чтение — линейное, ~2 000 ток/с. TTFT растёт с контекстом (4.2 с на 8k → 66 с на 128k), и именно чтение здесь узкое место.

  • Параллелизм ведёт себя как заявлено. Короткие контексты при c=4 дают максимум суммарного throughput (+27% к одиночному потоку), но батчинг замедляет каждый запрос по TTFT в 2–5 раз, а c=16 сервер уже не переваривает. Длинные одиночные запросы выгоднее слать по одному.

  • Для агентского сценария (прочитать контекст + ответ ~150 токенов) шаг целиком занимает ~6 с при 8k, ~18 с при 32k и ~68 с при 128k — комфортный рабочий контекст где-то до 32k.

А если оставить reasoning включённым?

Для полноты картины ту же матрицу прогнали и с включёнными размышлениями. Картинка получается занятная:

Метрика

Reasoning ON

Reasoning OFF

Запись @ 8k, форсированный вывод

~90–99 ток/с

96.4 ток/с

Запись @ 8k, свободный вывод

26.6 ток/с

—

Запись @ 128k, свободный вывод

2.6 ток/с

94.5 ток/с

TTFT до контента на тривиальном вопросе

6.76 с

0.18–0.35 с

Тонкость в том, что метрики здесь искажает сам способ измерения. TTFT отсчитывается до первого контентного токена, то есть включает все размышления целиком. А между контентными токенами вклиниваются паузы «подумать» — на 128k интервал доходит до 378 мс, что и выглядело как деградация до 2.6 ток/с. При форсированном выводе, когда паузы вымываются сплошным стримом, скорость записи почти не отличается от reasoning OFF (~90–99 против 96.4 ток/с): токены генерируются так же быстро — модель просто думает между ними.

Практический вывод: нужен быстрый и предсказуемый стрим — отключайте thinking. Если качество важнее latency — оставляйте, но помните, что свободная генерация с reasoning останавливается по EOS уже на 85–365 токенах, так что «честную» скорость записи вы в этом режиме всё равно не увидите.

И приятный бонус: за всё исследование — 150+ запросов, и после патча парсера ни одной ошибки и ни одного таймаута.

Готовим Fedora 43 Server

Ставим Podman и базовые утилиты:

sudo dnf upgrade --refresh -y
sudo dnf install -y podman curl pciutils
sudo reboot

После перезагрузки проверяем драйвер и GPU-устройства:

lspci -nnk | grep -A 4 -Ei 'VGA|Display|3D'
ls -l /dev/kfd /dev/dri/renderD*
free -h

Для работы с GPU пользователю обычно нужны группы render и video:

sudo usermod -aG render,video "$USER"

Дальше — важная мелочь, о которой часто забывают: полностью завершите SSH-сеанс и подключитесь заново, иначе новые группы не подхватятся.

Создаём API-ключ

HALOGEN умеет защищать API через переменную HALOGEN_API_KEY. Клиент передаёт её стандартным заголовком:

Authorization: Bearer ВАШ_КЛЮЧ

Создадим файл окружения с правами доступа только для текущего пользователя:

mkdir -p "$HOME/.config/halogen" "$HOME/halogen-models"
chmod 700 "$HOME/.config/halogen"

(
  umask 077

  if [ ! -f "$HOME/.config/halogen/server.env" ]; then
    printf 'HALOGEN_API_KEY=%s\n' \
      "$(head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n')" \
      > "$HOME/.config/halogen/server.env"
  fi
)

chmod 600 "$HOME/.config/halogen/server.env"

Посмотреть ключ можно так:

cat "$HOME/.config/halogen/server.env"

И банальное, но необходимое: не добавляйте этот файл в Git, не пересылайте в мессенджерах и не держите в публичных конфигурациях.

Запускаем HALOGEN с четырьмя параллельными сессиями

HALOGEN слушает порт 8731 внутри контейнера. Если внешний API должен быть доступен через 9091, порт-маппинг выглядит так: 9091 на хосте → 8731 в контейнере.

Команда запуска:

podman run -d \
  --name halogen \
  -p 0.0.0.0:9091:8731 \
  --device /dev/kfd \
  --device /dev/dri \
  --group-add keep-groups \
  --security-opt label=disable \
  --ipc=host \
  --ulimit memlock=-1:-1 \
  --env-file "$HOME/.config/halogen/server.env" \
  -e HALOGEN_KV_SLOTS=4 \
  -e HALOGEN_DOWNLOAD=peonist-ai/halogen-qwen3.8-flash-next \
  -v "$HOME/halogen-models:/models" \
  ghcr.io/peonist-ai/halogen-flash-server:0.18.5

Что здесь отвечает за что

Параметр

Назначение

-p 0.0.0.0:9091:8731

Публикует API наружу на порту 9091

--device /dev/kfd

Доступ к AMD Compute Runtime

--device /dev/dri

Доступ к DRM/GPU

--group-add keep-groups

Передаёт контейнеру права групп пользователя

--security-opt label=disable

Обход ограничений SELinux-разметки для GPU-доступа

--ipc=host

Общий IPC namespace, как рекомендует quickstart-конфигурация

--ulimit memlock=-1:-1

Снимает лимит блокируемой памяти

HALOGEN_KV_SLOTS=4

До четырёх одновременно генерирующих диалогов

HALOGEN_DOWNLOAD=...

Автоматическая загрузка весов при первом старте

--env-file

Подключает API-ключ, не светя им в командной строке

Посмотреть ход загрузки и инициализации модели:

podman logs -f halogen

И завершающий штрих — на мой взгляд, обязательная настройка. Разрешите пользователю работать в фоне, иначе при закрытии SSH-консоли сервер просто выключится:

sudo loginctl enable-linger "$USER"

Почему nvtop показывает всего ~27 ГБ «видеопамяти»

На Strix Halo показания nvtop регулярно вызывают вопросы. Модель занимает около 110 ГиБ на SSD, основной checkpoint требует примерно 62 ГиБ резидентной памяти — а nvtop показывает какие-то ~27 ГБ GPU memory.

Это нормально, и вот почему.

Отдельной физической VRAM у Strix Halo нет: iGPU использует RAM хоста, и HALOGEN не обязан отображать весь объём модели как классическую GPU VRAM. Память распределяется примерно так:

  • основные веса живут в резидентной памяти и занимают около 62 ГиБ;

  • N-gram table на 47,7 ГиБ подключена через mmap — Linux подтягивает её страницы по мере необходимости и греет их в page cache.

В nvtop при этом обычно хорошо видны буферы GPU, рабочие области вычислений, KV-cache и часть GPU memory mapping. При HALOGEN_KV_SLOTS=4 заметную долю тех самых ~27 ГБ съедает общий KV-pool и состояние слотов.

Так что цифра в nvtop не означает, что модель загрузилась «только на 27 ГБ» или работает не в полную силу.

Расширяем контекст до миллиона токенов через YaRN

Нативный контекст модели — 262 144 токена, но это не потолок. HALOGEN умеет растягивать позиционный контекст через YaRN, и задаётся это двумя переменными окружения:

-e HALOGEN_ROPE_YARN=4 \
-e HALOGEN_CTX=1048576 \

В такой конфигурации максимальная длина контекста вырастает с 262 144 до 1 048 576 токенов. Важно: настройки читаются при запуске, поэтому контейнер нужно пересоздавать, а не просто перезапускать.

Сколько это съедает на практике? Живой замер при миллионном контексте и одном слоте: HALOGEN занимает 36,7 ГиБ по данным nvtop и 38,9 ГиБ по htop (для сравнения — около 27 ГиБ в nvtop на нативном контексте с четырьмя слотами). То есть сам по себе миллион запускается вполне уютно. Но «запускается» и «работает как станция» — вещи разные: если машина нужна именно как полноценная станция с миллионным контекстом, закладывайте порядка 96 ГиБ памяти — под веса, выросший KV-пул и запас под page cache. 128-гигабайтный Strix Halo такое закрывает с запасом, а на 64 ГБ замахиваться на миллион уже не стоит.

Для первого захода с таким контекстом советую один слот (HALOGEN_KV_SLOTS=1) — незачем делить и без того растянутый KV-пул между четырьмя запросами. Веса из $HOME/halogen-models и API-ключ из env-файла никуда не денутся, ничего заново качать не придётся. А чтобы не трогать исходный контейнер, второй заведём под другим именем — halogen-yarn:

podman run -d \
  --name halogen-yarn \
  -p 0.0.0.0:9091:8731 \
  --device /dev/kfd \
  --device /dev/dri \
  --group-add keep-groups \
  --security-opt label=disable \
  --ipc=host \
  --ulimit memlock=-1:-1 \
  --env-file "$HOME/.config/halogen/server.env" \
  -e HALOGEN_KV_SLOTS=1 \
  -e HALOGEN_ROPE_YARN=4 \
  -e HALOGEN_CTX=1048576 \
  -e HALOGEN_DOWNLOAD=peonist-ai/halogen-qwen3.8-flash-next \
  -v "$HOME/halogen-models:/models" \
  ghcr.io/peonist-ai/halogen-flash-server:0.18.5

Единственный нюанс: если основной контейнер halogen всё ещё работает, порт 9091 у него занят — остановите его перед запуском второго, два контейнера не смогут слушать один и тот же порт.

Не публикуйте HTTP API в интернете без TLS

API-ключ защищает сервер от чужих запросов, но шифровать соединение он не умеет. По чистому HTTP токен и содержимое запросов может перехватить любой, кто стоит по пути.

Правильная production-схема выглядит так:

Интернет
    ↓ HTTPS :9091
Caddy / Nginx / Traefik
    ↓ HTTP 127.0.0.1:8731
HALOGEN

Вместо итога

Связка из AMD Strix Halo, 128 ГБ RAM, Fedora 43 Server и HALOGEN позволяет поднять быстрый локальный API для Qwen3.8-Flash-Next — без дискретной GPU. На выходе получается:

  • MoE-модель на 125B параметров с 6B активных на токен;

  • около 110 ГиБ весов на диске;

  • 50+ токенов/с для одного интерактивного потока на рабочих задачах при отключенном reasoning;

  • до четырёх параллельных генераций через HALOGEN_KV_SLOTS=4;

  • OpenAI-совместимые /v1/chat/completions, /v1/completions и /v1/responses;

  • доступ извне через порт 9091;

  • авторизация через HALOGEN_API_KEY.

Главное отличие этой конфигурации от «просто LLM-сервера» — правильная работа с UMA-памятью: низкий UMA carve-out в BIOS, понимание роли memory-mapped N-gram table и отказ от идеи читать показания nvtop как полный объём памяти, занятой моделью.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.