TL;DR. Я купил мини‑ПК с Ryzen AI 9 365, чтобы гонять большую локальную модель на NPU. Начал с Windows ради гибрида NPU+iGPU, который так и не заработал, прошёл квест с драйвером NPU, выяснил, что NPU видит только половину оперативки, переехал на Proxmox и в итоге запустил Qwen3.6–35B‑A3B через FastFlowLM прямо на хосте. Модель работает 24/7: prefill около 200 ток/с, decode 13–17 ток/с. По дороге выяснилось, что NPU обслуживает один запрос за раз, падает с double free, если клиент не дождался ответа, и умеет выгнать из памяти большую модель ради маленькой embedding‑модели. Ниже вся дорога по порядку, мини‑гайд и цифры. Читать далее
Уровень сложностиСредний
Время на прочтение13 мин
Охват и читатели29K
Кейс

TL;DR. Я купил мини‑ПК с Ryzen AI 9 365, чтобы гонять большую локальную модель на NPU. Начал с Windows ради гибрида NPU+iGPU, который так и не заработал, прошёл квест с драйвером NPU, выяснил, что NPU видит только половину оперативки, переехал на Proxmox и в итоге запустил Qwen3.6–35B‑A3B через FastFlowLM прямо на хосте. Модель работает 24/7: prefill около 200 ток/с, decode 13–17 ток/с. По дороге выяснилось, что NPU обслуживает один запрос за раз, падает с double free, если клиент не дождался ответа, и умеет выгнать из памяти большую модель ради маленькой embedding‑модели. Ниже вся дорога по порядку, мини‑гайд и цифры.

Маршрут статьи
Маршрут статьи: грабли расставлены в том порядке, в котором я на них наступал.
С чего началосьДомашний сервер был на Ryzen 7 5800U: без видеокарты и без NPU. Локальная LLM на CPU работала, но на длинных промптах всё время уходило не на ответ, а на чтение:
Фаза | Токены | Время | Скорость |
|---|---|---|---|
Prefill (чтение промпта) | 7943 | 245,1 с | 32,4 ток/с |
Decode (генерация) | 36 | 5,0 с | 7,05 ток/с |
Итого | 7979 | 250 с | - |
99% времени модель читала. И тут маркетинг AMD говорит ровно то, что хочется услышать: NPU хорош именно в prefill. Хочу. Зачем мне вообще локальная модель, а не облако, расскажу в третьем акте, там же посчитаем деньги.

Выбирал между мини‑ПК на Ryzen AI 9 365 и Ryzen AI 9 HX PRO 370. Взял Ryzen AI 9 365 (NPU XDNA2, Radeon 880M) и 64 ГБ RAM. Тогда 64 ГБ казались запасом. Позже выяснилось, что это минимум.

Мини‑ПК FIREBAT на Ryzen AI 9 365
Конкретно — мини‑ПК FIREBAT на Ryzen AI 9 365. Сама коробка без памяти и SSD стоила 30 тыс. ₽, SSD переехал со старого мини‑ПК, а 64 ГБ DDR5-4800 (2 × 32 ГБ) обошлись ещё в 40 тыс. ₽. Итого около 70 тыс. ₽ (~$825), и память оказалась дороже самого компьютера.
Чем вообще запускать LLM на NPUПервое открытие: привычный стек тут не помогает.
llama.cpp / Ollama / LM Studio про NPU не знают. CPU, GPU через Vulkan или ROCm, а NPU простаивает.
Lemonade Server от AMD обещает самое вкусное: гибрид, где NPU считает prefill, а встроенная графика — decode. Но гибрид работает только с ONNX‑моделями, которые AMD заранее подготовила, и официально только на Windows. И выбор там скромный: в актуальном Ryzen AI 1.8 это Llama 3.2 1B/3B, Llama 3.1 8B, Qwen3 1.7B/4B/8B, Qwen2.5 до 7B, Mistral 7B, Phi-4-mini. Потолок — 8B, в прошлой версии попадались Qwen2.5–14B и Qwen3-14B.
FastFlowLM (flm) — отдельный рантайм под NPU AMD. Отдаёт OpenAI‑совместимый API, модели берёт из своего каталога на Hugging Face в формате .q4nx. Есть сборки под Windows и Linux. И в каталоге есть Qwen3.6–35B‑A3B с разбором картинок.
Мне хотелось модель побольше: чем больше, тем лучше, и чтобы умела разбирать картинки. Хотелось Qwen3.6–35B. Но гибрид всё равно был слишком заманчивым, чтобы его не проверить. Картинка в голове была такая: NPU быстро читает промпт, встроенная графика генерирует ответ, каждый чип занят своим делом. Гибрид живёт на Windows, значит, начинаем с Windows.
Акт 1. WindowsLemonade: посмотрел и закрылПервым делом поставил Lemonade и открыл список моделей. Всё, что помечено как Hybrid, — те самые мелкие модели, которые даже тестировать не хочется. Для Qwen3.6–35B гибрида нет: либо NPU через FLM, либо iGPU через llama.cpp, но не оба сразу. На этом мечта о гибриде закончилась, и я перешёл на FLM без всякого Lemonade.
Квест: драйвер NPUСтавлю FLM, ввожу flm, flm help, flm validate — тишина. Ни вывода, ни ошибки. Код возврата -1073741511, то есть 0xC0000139: бинарник не нашёл нужную функцию в DLL. Виноват старый драйвер NPU.
Найти свежий драйвер NPU — отдельный квест. Последние драйверы с сайта AMD не означают последний драйвер NPU. Отдельно он лежит в составе Ryzen AI Software, но чтобы его скачать, нужно зарегистрироваться и пройти проверку, что ты не из «недружественной» для AMD страны. Из России, Казахстана и Нидерландов доступ я так и не получил.
Изрядно попотев, драйвер я всё‑таки обновил, и flm ожил.
Qwen3.6–35B‑A3B скачалась, запустилась, отвечает. Подключаю Open WebUI, задаю вопрос, и flm падает с DMA Paging Error 0xc01e0200. Не всегда, а когда UI шлёт два запроса подряд: скрытую генерацию заголовка чата и сам ответ.
Открываю «Диспетчер задач»:
Windows видит 47,6 ГБ из 64.
«Выделенная память GPU» — 15,8 ГБ, занят из них 1 ГБ. BIOS заранее откусил их под встроенную графику, и они простаивают.
«Общая память» у NPU — 23,8 ГБ. Ровно половина от 47,6.
То есть NPU доступно около 50% оперативки, которую видит ОС, а резерв BIOS под iGPU срезает и саму эту базу. Модель весит ~20 ГБ, на KV‑cache и второй запрос остаётся 3,8 ГБ. Отсюда и падения.
Лечится в BIOS: UMA Frame Buffer Size (он же iGPU Memory) в минимум.

Пул NPU до и после правки BIOS
После правки: ОС видит 63,1 ГБ, пул NPU 31,6 ГБ, модель занимает 21,2 из них.
Вывод для тех, кто выбирает железо: на 32 ГБ такая модель не живёт. В issue #242 у людей с 32 ГБ даже GPT‑OSS-20B (~14 ГБ) не влезала стабильно. Считайте так: модель плюс запас на контекст должны помещаться в половину RAM за вычетом резерва под iGPU.
«NPU загружен всего на 50%»Модель работает, смотрю на график NPU: пила на 50–60%. Первая мысль — что‑то недонастроено. Нет. У MoE‑модели с ~3B активных параметров на токен вычислений мало, и NPU ждёт память: по документации FLM полоса у NPU около 60 ГБ/с против ~125 ГБ/с у iGPU. Decode упирается в память, так что 100% не будет.
И Open WebUI туда жеПопутная находка: Open WebUI с включёнными инструментами уходит в бесконечный цикл. Модель с 3B активных параметров генерирует дубли tool_calls, UI ругается и отправляет весь диалог заново, с полным re‑prefill. Лимит CHAT_RESPONSE_MAX_TOOL_CALL_ITERATIONS по умолчанию 256; ставьте 2–3.
И тут в голову пришла простая мысль: а зачем я страдаю на Windows? Гибрид NPU+iGPU, ради которого я сюда пришёл, уже провалился, работать будет только NPU, а FLM одинаково ставится и на Linux. К тому же на этой машине я хотел поднять свои виртуалки, а возиться с виртуализацией на Windows не хотелось. Итог: Proxmox VE 9 (Debian 13).
План А: LLM в виртуалкеРаз всё остальное живёт в ВМ, логично и LLM туда же. Классика: ВМ с Ubuntu, пробрасываем устройство, внутри flm. Не работает. Встроенная графика через VFIO пробрасывается, NPU — нет: софт к этому пока не готов. На форуме Proxmox даже тема так и называется: «iGPU funktioniert — NPU aktuell nicht».
План Б: FLM прямо на хостеДрайвер NPU живёт в ядре хоста, поэтому flm ставится на сам Proxmox, рядом с гипервизором. Арифметика по памяти: 64 ГБ, из них ~21 ГБ модель, 10–15 ГБ виртуалки. Виртуалкам — жёстко зарезервированную память без ballooning, иначе в момент инференса хост может не найти страниц под буферы flm.
Приятный сюрприз после Windows: на Linux драйвер NPU уже есть в ядре Proxmox, никаких регистраций.
Мини‑гайд: FLM на Proxmox 9 / Debian 13Компонент | Версия |
|---|---|
CPU | AMD Ryzen AI 9 365 w/ Radeon 880M (NPU XDNA2) |
RAM | 64 ГБ, UMA Frame Buffer в BIOS — минимум |
ОС | Proxmox VE 9.2 (Debian 13 trixie) |
Ядро | 7.0.2-6-pve, драйвер |
XRT |
|
FastFlowLM | 1.0.5 |
Модель |
|
uname -r # свежее ядро, у меня 7.0.2-6-pve
lsmod | grep amdxdna # драйвер загружен
ls -l /dev/accel/ # должен быть accel0
dmesg | grep -i xdna # прошивка загрузилась без ругани
На Proxmox 9 всё это было «из коробки». На старых ядрах бывает Incompatible firmware protocol — тогда обновлять ядро.
FLM зависит от XRT (userspace‑часть для NPU). В стабильном trixie этих пакетов нет, поэтому я не подключал sid целиком, а взял два готовых deb‑файла из его пула:
cd /tmp
wget https://github.com/ROCm/FastFlowLM/releases/download/v1.0.5/fastflowlm\_1.0.5\_debian13\_amd64.deb
wget http://deb.debian.org/debian/pool/main/x/xrt/libxrt2\_2.25.0-4\_amd64.deb
wget http://deb.debian.org/debian/pool/main/x/xrt/libxrt-npu2\_2.25.0-4\_amd64.deb
apt install -y ./libxrt2_2.25.0-4_amd64.deb ./libxrt-npu2_2.25.0-4_amd64.deb \
./fastflowlm_1.0.5_debian13_amd64.deb
flm validate # ядро, устройство, прошивка, memlock - всё зелёное
Версии в пуле sid со временем меняются: если ссылка отдаёт 404, актуальное имя файла ищите на packages.debian.org/sid/libxrt2.
3. Модельmemlock. FLM нужен
unlimitedmemlock, иначе не выделятся буферы под NPU. Deb‑пакет прописал его сам. Еслиulimit -lв SSH‑сессии показывает другое, это особенность non‑interactive shell.
flm list # ✅ скачано, ⏬ нет
flm pull qwen3.6-moe:35b-a3b # ~20 ГБ, запускать в tmux
4. Сервер под systemd# /etc/systemd/system/flm-serve.service
[Unit]
Description=FastFlowLM serve (qwen3.6-moe:35b-a3b)
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/flm serve qwen3.6-moe:35b-a3b --host 0.0.0.0 --port 52625 --ctx-len 131072
Restart=on-failure
RestartSec=5
User=root
[Install]
WantedBy=multi-user.target
Признак, что сервер поднялся, а не тихо умер после Loading model:
[FLM] WebServer started on port 52625 with 10 I/O threads
Restart=on-failure и --ctx-len тут не для красоты. Зачем они, станет ясно в третьем акте.
root@proxmox:~# curl http://localhost:52625/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"model":"qwen3.6-moe:35b-a3b","messages":[{"role":"user","content":"Привет! /no_think"}]}'
{
"model": "qwen3.6-moe:35b-a3b",
"choices": [{ "message": { "role": "assistant", "content": "Привет! Чем могу помочь?" },
"finish_reason": "stop" }],
"usage": {
"prompt_tokens": 16,
"completion_tokens": 9,
"kv_token_occupancy_rate_percentage": 0.019,
"prefill_duration_ttft": 2.7097,
"decoding_duration": 0.6241,
"prefill_speed_tps": 5.90,
"decoding_speed_tps": 14.42
}
}
Помимо стандартного usage, FLM отдаёт честные метрики движка: время и скорость prefill и decode. Сохраняйте их, они ещё пригодятся.
И сразу первый повод присмотреться: prefill 5,9 ток/с на 16 токенах. Это не поломка. У Qwen3.6–35B‑A3B на NPU есть фиксированная задержка около 2,7 с на любой запрос: prefill раскладывается на ~4900 последовательных вызовов NPU по экспертам (issue #710). На коротком промпте эти 2,7 с и есть всё время, на длинном они теряются.
Акт 3. Ради чего всё этоТеперь о том, зачем мне понадобилась локальная модель. Мои сервисы шлют частые запросы до ~32k токенов, в сумме около 6 млн токенов в сутки: 5,5 млн входящих и 0,5 млн исходящих. Сколько это стоит в облаке по ценам на сентябрь 2026:
Модель | Вход / выход, $ за 1M | В сутки | В месяц | В год |
|---|---|---|---|---|
DeepSeek Flash | 0,15–0,30 / 0,60–1,20 | $1,1–2,3 | $34–68 | $411–821 |
DeepSeek V4 Pro | 0,66–1,32 / 1,98–3,96 | $4,6–9,2 | $139–277 | $1 686–3 373 |
OpenAI GPT-5.6 Luna | 0,20 / 1,20 | $1,7 | $51 | $621 |
OpenAI GPT-6 Sol | 2 / 10 | $16 | $480 | $5 840 |
Claude Haiku 4.5 | 1 / 5 | $8 | $240 | $2 920 |
Claude Sonnet 5 | 2 / 10 | $16 | $480 | $5 840 |
Claude Opus 5.5 | 4 / 20 | $32 | $960 | $11 680 |
Без учёта кеша промптов и batch‑скидок. У DeepSeek вилка — это ночной и дневной тариф.
Для сравнения: весь мини‑ПК обошёлся в ~$825. Против Claude Sonnet 5 или GPT-6 Sol он окупается меньше чем за 2 месяца, против Claude Haiku 4.5 — примерно за 3,5 месяца, против самого дешёвого DeepSeek Flash — за год‑два.
Сначала я, конечно, сидел на бесплатных API. Они оказались нестабильными: примерно половина запросов падала с ошибкой, начинались ретраи, ретраи тоже падали, и всё уходило в круговорот ошибок. Локальная модель решает обе проблемы: платишь один раз, а падает она только по твоей вине. Ну, почти.
Пока с моделью разговариваешь в чате, всё прекрасно. Но как только к ней подключились сервисы, которые шлют запросы сами, пачками и круглосуточно, началось самое интересное.
Сюрприз 1: время ответа скачет в разыЗапросы одного размера выполнялись то за 35 секунд, то за 170. Метрики FLM всё объяснили: NPU обслуживает строго один запрос за раз. У flm serve есть FIFO‑очередь (--q-len, по умолчанию 10), но параллелизма нет.

Таймлайн двух запросов в очереди NPU
Два запроса пришли в одну секунду. Расчётное время Б — 55,6 с, фактическое — 114,7 с. Разница равна времени запроса А.
Сюрприз 2: double freeОчередь — полбеды. У HTTP‑клиентов стоял дефолтный таймаут 120 секунд. Запрос ждёт в очереди, клиент не дожидается и отменяет его, а FLM на отмене во время prefill падает целиком. Вместе с ним пропадает и вся очередь:
Client disconnected; cancelling active request
Prefill Cancelled
Clearing context...
double free or corruption (!prev) # или просто SIGSEGV
Худший случай: один сервис накидал 26 параллельных запросов с max_tokens: 70000. Очередь росла от 1 до 26 и ни разу не убывала, потом пошла лавина отмен, и flm лёг. Этот баг открыт в апстриме: issue #608.

Что помогло:
Таймауты клиентов — минуты, у меня 20 на тяжёлые задачи. Пусть лучше ждёт, чем отменяет.
Restart=on-failure: systemd поднимает flm за ~15 с. Баг остался, но перестал будить меня ночью.
--ctx-len явно. По умолчанию 32k, и промпт на ~38k токенов давал max length reached during prefill и тот же крэш.
Тяжёлые промпты — не на NPU. Запрос на ~38k токенов держал NPU 6–7 минут, всё остальное копилось сзади. Такие задачи я увёл во внешнее API.
Когда к NPU ходили уже три независимых сервиса, каждый со своей конкурентностью, в логе FLM появилось Connection limit reached (10), rejecting new connection. Каждый сервис по отдельности вёл себя прилично, но о других ничего не знал.

Первая идея — --q-len 1, чтобы FLM сам жёстко сериализовал запросы. Стало хуже: один зависший запрос занимает единственный слот, остальные получают 503. С очередью 10 зависание — это задержка, с очередью 1 — полный отказ. Вернул дефолт.
Рабочее решение — один вышибала на входе: LiteLLM‑прокси (llm‑proxy) перед flm с глобальным лимитом на весь трафик.

Фейс‑контроль llm‑proxy перед NPU
model_list:
- model_name: flm-chat
litellm_params:
model: openai/qwen3.6-moe:35b-a3b
api_base: http://<flm-host>:52625/v1
api_key: "not-needed"
general_settings:
master_key: os.environ/LITELLM_MASTER_KEY
global_max_parallel_requests: 3 # потолок на весь трафик к NPU
store_prompts_in_spend_logs: true # иначе в Request Logs "Data Not Available"
Разные model_name на один бэкенд — дешёвый способ видеть в логах, какой клиент сколько ест, без virtual keys и базы.
Пробы прокси вешайте на /health/liveliness. Обычный /health дёргает сам flm, а тот отвечает минутами.
Колонке TTFT в логах LiteLLM не верьте: для нестриминговых запросов она равна общему времени. Настоящий TTFT лежит в usage от FLM, в поле prefill_duration_ttft.
Сервисам нужен короткий JSON, а не рассуждения. Ни enable_thinking: false, ни chat_template_kwargs, ни think на Qwen3.6 через flm не действуют. Это болезнь самой Qwen3.6, в vLLM, SGLang и llama.cpp то же самое. Работает /no_think прямо в промпте: 59 токенов ответа без него и 2 с ним. Для задач «ответь строго JSON» хватает и явной инструкции.
Для поиска похожих текстов понадобились эмбеддинги. В каталоге FLM есть embed-gemma:300m, включается флагом --embed 1. Пока NPU свободен, всё отлично: 0,29 с на вектор из 768 чисел. Под нагрузкой рядом с 35B‑моделью запрос висит минутами, а иногда в логе появляется:
[ERROR] Unsupported model family or non-llm: "embed-gemma"
После этого flm выгружает 35B, грузит llama3.2:1b, отвечает ею и грузит 35B обратно. Несколько минут простоя для всех клиентов.

Решение: та же embeddinggemma-300M в GGUF Q8_0 через llama.cpp на CPU, отдельной записью в том же llm‑proxy. Результат: 0,06–0,11 с на запрос, 15 запросов подряд без единого сбоя. Маленькой модели NPU не нужен, а общую очередь она ломает.
ЦифрыВсе замеры ниже — Qwen3.6–35B‑A3B на Ryzen AI 9 365 через FLM 1.0.5, реальные запросы из логов, без очереди.
Запрос | Вход, ток. | Выход, ток. | Prefill, ток/с | Decode, ток/с |
|---|---|---|---|---|
«Привет» из curl выше | 16 | 9 | 5,9* | 14,4 |
Текст | 1 046 | 192 | 109,1 | 17,1 |
Картинка + промпт | 1 127 | 61 | 99,1 | 16,9 |
Текст | 5 699 | 98 | 193,2 | 15,6 |
Текст | 6 135 | 103 | 196,9 | 15,7 |
Текст | 6 902 | 405 | 205,6 | 15,7 |
Текст | 17 653 | 1 187 | 209,9 | 13,3 |
Текст | 17 980 | 1 375 | 211,4 | 13,2 |
* фиксированные ~2,7 с на запрос, см. «Ссылки».

Скорость prefill и decode от размера промпта
Картина понятная: чем длиннее промпт, тем быстрее prefill (фиксированные накладные расходы размазываются) и тем медленнее decode (растёт KV‑cache). Картинка лишь немного медленнее текста того же размера. Для прикидки на промптах 5–18k токенов: prefill ~200 ток/с, decode ~13–16 ток/с.
Официальный бенчмарк FLM для той же модели (Ryzen AI 7 350, 96 ГБ)Контекст | Prefill, ток/с | Decode, ток/с |
|---|---|---|
1k | 102 | 17,5 |
32k | 281 | 11,2 |
Мои цифры с ним хорошо сходятся: на 1k токенов почти один в один.
CPU, NPU и RTX 3090
CPU, NPU и RTX 3090: prefill и decode
Против старого CPU выигрыш заметный: prefill в ~6 раз, decode в ~2 раза. Среднее время вызова упало с ~513 с до ~78 с, но это смесь «NPU быстрее» и «очередь на CPU была хуже».
Против видеокарты NPU проигрывает всухую: у RTX 3090 на той же модели в Q4 prefill ~2400–2600 ток/с (в 13 раз быстрее), decode ~60–75 ток/с (в 4–5 раз). Выигрывает NPU в другом: тишина, энергопотребление и 35B‑модель в коробке размером с коробку из под печенья.
Итого: стоит ли оно тогоДа, если:
нужна большая MoE‑модель 24/7 в тихой коробке
нагрузка — фоновая очередь задач, а не живой чат
промпты длинные, ответы короткие
Нет, если:
нужен параллелизм: NPU один, очередь одна
нужна интерактивность: 13–17 ток/с в чате медленно
модель с контекстом больше половины RAM
А у вас есть опыт с NPU от AMD или Intel? Кто‑нибудь завёл гибрид NPU+iGPU на Linux на модели крупнее 8B? Делитесь в комментариях: информации по этой теме мало, и каждая история на вес золота.
СсылкиFastFlowLM: github.com/ROCm/FastFlowLM, документация
Issues: #242 (gpt‑oss-20b на 32 ГБ), #608 (double free под нагрузкой), #710 (фиксированные 2,7 с TTFT у Qwen3.6–35B‑A3B)
Hybrid‑модели AMD на Hugging Face (ищите суффикс _hybrid)
| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | LLM уверенно называет шахматные ходы, которых на доске нет. Как я проверяю каждый ее ответ кодом | 0 | 5.87 | 26-09-2026 |
| 2 | Я прогнал топ VRAM-калькуляторов для LLM — все ошибаются в одном и том же | 0 | 10.17 | 08-09-2026 |
| 3 | Локальные нейросети без Python, CUDA и терминала: делаю программу, в которой всё настраивается само | 0 | 7.01 | 27-09-2026 |
| 4 | RuntimeNodes: как мы, ML‑щики, стали писать рантайм | 0 | 7.74 | 24-09-2026 |
| 5 | Не трогая веса модели: как мы построили исследовательского агента Алисы AI и в разы сократили потребление GPU | 1 | 8.1 | 14-09-2026 |
| 6 | Контекст растёт, KV-кэш — нет: Qwen3.8-27B на ограниченной VRAM с CMF формате | 0 | 22.4 | 09-09-2026 |
| 7 | Облачные провайдеры берут плату не за железо, а за лень ... | 0 | 11.1 | 27-09-2026 |
| 8 | Daily Hacker News for 2026-09-20 | 0 | 9.38 | 21-09-2026 |
| 9 | Омнимодель для Алисы AI: как нам удалось подружить VLM и LLM | 0 | 7.4 | 03-09-2026 |
| 10 | Облачные провайдеры берут плату не за железо, а за лень ... | 0 | 14.96 | 28-09-2026 |