
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. Сама коробка без памяти и 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. Windows
Lemonade: посмотрел и закрыл
Первым делом поставил 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) в минимум.

После правки: ОС видит 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.
Акт 2. Почему всё‑таки Linux
И тут в голову пришла простая мысль: а зачем я страдаю на 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 |
Модель |
|
1. Проверяем, что ядро видит NPU
uname -r # свежее ядро, у меня 7.0.2-6-pve lsmod | grep amdxdna # драйвер загружен ls -l /dev/accel/ # должен быть accel0 dmesg | grep -i xdna # прошивка загрузилась без ругани
На Proxmox 9 всё это было «из коробки». На старых ядрах бывает Incompatible firmware protocol — тогда обновлять ядро.
2. XRT и FastFlowLM
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.
memlock. FLM нужен
unlimitedmemlock, иначе не выделятся буферы под NPU. Deb‑пакет прописал его сам. Еслиulimit -lв SSH‑сессии показывает другое, это особенность non‑interactive shell.
3. Модель
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 тут не для красоты. Зачем они, станет ясно в третьем акте.
5. Проверка
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), но параллелизма нет.

Два запроса пришли в одну секунду. Расчётное время Б — 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.
Сюрприз 3: Connection limit reached (10)
Когда к NPU ходили уже три независимых сервиса, каждый со своей конкурентностью, в логе FLM появилось Connection limit reached (10), rejecting new connection. Каждый сервис по отдельности вёл себя прилично, но о других ничего не знал.

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

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.
Сюрприз 4: thinking не выключается
Сервисам нужен короткий JSON, а не рассуждения. Ни enable_thinking: false, ни chat_template_kwargs, ни think на Qwen3.6 через flm не действуют. Это болезнь самой Qwen3.6, в vLLM, SGLang и llama.cpp то же самое. Работает /no_think прямо в промпте: 59 токенов ответа без него и 2 с ним. Для задач «ответь строго JSON» хватает и явной инструкции.
Сюрприз 5: embedding выгоняет большую модель
Для поиска похожих текстов понадобились эмбеддинги. В каталоге 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 (растёт 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 выигрыш заметный: 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)

