Локальный инференс на встроенной AMD-графике: ROCm-хак и честные токены в секунду

У меня в лабе живёт мини-ПК на AMD Phoenix: внутри встроенная графика Radeon 760M (ядро gfx1103), 16 ГБ общей памяти, и ни одной дискретной карты. На первый взгляд — что там гонять, это же iGPU от ноутбучного кристалла. Но у него есть то, чего нет у процессора: настоящий GPU-пайплайн и прямой доступ к общему куску быстрой памяти. А у меня давно чесалось запустить локальную LLM — без аренды видеокарты в облаке и без отправки своих вопросов на чужие серверы.
Спойлер: завелось и работает. Но не так, как обещают красивые посты «локальный DeepSeek за пять минут на любом железе». Давайте по порядку — боль, решение, честные цифры и грабли.
Зачем вообще локально
Сначала про мотивацию, потому что без неё весь этот геморрой выглядит бессмысленным. Локальная модель — это три вещи. Первое: приватность, вопросы не уезжают в чужое облако. Второе: нет счётчика за токены, гоняешь сколько влезет. Третье: она не падает вместе с API-провайдером и не ловит лимиты в час пик. Для рутины и черновиков этого достаточно. А вот для vision, тяжёлых агентов и огромных контекстов — уже нет, но об этом ниже.
Боль: AMD в контейнере — отдельный вид спорта
У Nvidia в контейнерах всё отлажено годами: пробросил /dev/nvidia*, поставил nvidia-container-toolkit — поехало. У AMD за это отвечает протокол ROCm. Под дискретные карты он ещё как-то жил, а вот встроенная графика долго числилась пасынком: официально gfx1103 в ROCm не значится, поддержки «из коробки» нет.
Вторая проблема — окружение. Я держу всё в LXC-контейнерах под Proxmox, а не в голом Docker на хосте. LXC — это не виртуалка и не докер: устройств из коробки не видно, udev внутри не рулит, права на /dev надо городить руками. То есть классического «развернул и забыл» тут не будет в принципе. Каждый шаг — ручная настройка.
Проброс устройств: три ноды и никакой магии
Внутри контейнера Ollama должен увидеть три устройства:
/dev/dri/renderD128— вычислительный узел рендера, именно через него идут вычисления;/dev/dri/card0— карта как устройство отображения;/dev/kfd— Kernel Fusion Driver, дверь в ROCm-стек.
Проброс на Proxmox делается одной командой через pct set:
pct set 107 -dev0 /dev/dri/renderD128 -dev1 /dev/dri/card0 -dev2 /dev/kfd
Устройства в контейнере появятся, но права по умолчанию будут root. А Ollama у меня бегает не от root — и без прав на эти ноды он упадёт на первой же секунде. Внутри LXC не работает udev, поэтому выставляю права через tmpfiles.d: правило отрабатывает при старте контейнера и раздаёт владельца и группу:
# /etc/tmpfiles.d/gpu.conf
z /dev/dri/renderD128 0666 root render -
z /dev/dri/card0 0666 root video -
z /dev/kfd 0666 root render -
Всё, сервис видит железо. Но само железо ещё «не говорит по-человечески».
ROCm-хак: выдаём gfx1103 за gfx1100
Вот ради чего пост называется «хаком». Встроенная графика в моём кристалле — gfx1103, и ROCm её официально не знает. Но архитектурно gfx1103 — почти близнец дискретного gfx1100, ядра той же линейки RDNA3. В ROCm есть переменная, которая подменяет идентификатор GPU для драйвера:
HSA_OVERRIDE_GFX_VERSION=11.0.0
«Прикинься gfx1100» — и стек начинает грузить ядра для него. Плюс вторая переменная, которая говорит Ollama, что на встроенную графику можно:
OLLAMA_IGPU_ENABLE=1
Обе вешаю через drop-in юнита, чтобы не трогать сам systemd-файл сервиса:
# /etc/systemd/system/ollama.service.d/gpu.conf
[Service]
Environment=HSA_OVERRIDE_GFX_VERSION=11.0.0
Environment=OLLAMA_IGPU_ENABLE=1
daemon-reload, рестарт сервиса — и смотрим, подхватилась ли карта.
Честные цифры: что реально получилось
Сначала убеждаюсь, что инференс реально ушёл на GPU, а не молотится на CPU втихаря. ollama ps показывает процессор, на котором крутится модель, и там красуется:
PROCESSOR 100% GPU
Это самый приятный момент во всей истории — когда после пары часов ковыряния видишь, что встроенная графика честно тянет модель, а не процессор делает вид. Теперь цифры.
gemma3:12b — основная рабочая лошадка:
- 8,1 ГБ на диске;
- 8,0 ГБ в видеопамяти;
- 14,8 токена/сек;
- контекст 131072 токена.
gemma3:4b — запасная:
- 3,3 ГБ;
- 23,5 токена/сек;
- контекст 32768.
Для сравнения был ещё fp16-вариант — и он разочаровал: те же 8,1 ГБ видеопамяти, но всего 8,1 ток/сек. Вдвое дороже по ресурсам, вдвое медленнее, а прироста качества на глаз ноль. Выкинул без сожалений.
Важная деталь: у встроенной графики нет своей выделенной видеопамяти, она заимствует её у общей системной. Поэтому 8 ГБ «VRAM» — это те же 8 ГБ из 16 ГБ оперативки. Модель на 12b сюда влезает впритык, а на 16b уже не хватило бы с запасом на контекст. Это и есть главный потолок iGPU — не скорость, а память.
14–24 токена в секунду — это не «вау, летает». Это уровень «читает примерно с той же скоростью, что и я»: ответы не мгновенные, но и не бесконечные. Для локального помощника, которому задал вопрос и ждёшь абзац, — комфортно. Для потоковой генерации больших текстов — уже на грани.
Где ожидания врут
Вот тут самое важное. Картинка «завёл локальный LLM на iGPU и получил бесплатного ChatGPT» красивая, но в ней три жирные оговорки.
Вижн не работает. Ни на одной модели. CLIP-энкодер, который разбирает картинки перед подачей в модель, на ROCm gfx1100 просто падает. Картинки в этой связке — только через облачную vision-модель, и точка.
Длинные промпты роняют 12b. Скармливаешь конфиг или документ больше 10 КБ — gemma3:12b улетает с CUBLAS_STATUS_INTERNAL_ERROR. Короткие промпты стабильны, длинные — русская рулетка. Младшая gemma3:4b длинные тексты, кстати, переваривает (30 КБ тянет), но медленно и с маленьким окном контекста.
8B-модели не годятся в агентский режим. Пробовал hermes3:8b и llama3.1:8b в роли субагентов, которые должны ходить по инструментам и писать отчёты, — вместо отчёта получал мусор. Удалил с диска. Локально хорошо работает «ответь на вопрос», а не «пойди и сделай».
Итого: встроенная AMD-графика — это честный локальный инференс для приватных вопросов, черновиков и простой рутины. Но не замена облачному vision, не площадка для тяжёлых агентов и не бесконечное окно контекста. Знать это заранее — половина успеха, чтобы потом не расстраиваться.
Итог
Если у вас мини-ПК на свежем AMD и хочется попробовать локальную LLM без вложений в видеокарту — заводится. Рецепт: пробросить три устройства в контейнер, выставить права через tmpfiles.d, подменить gfx1103 на gfx1100 переменной HSA_OVERRIDE_GFX_VERSION и разрешить iGPU через OLLAMA_IGPU_ENABLE. Дальше — смотреть на PROCESSOR 100% GPU и радоваться, что вопросы больше не уезжают в чужое облако.
Просто помните: это iGPU, а не дата-центр. 15–24 токена в секунду, без вижна, с капризами на длинных промптах и потолком в 16 ГБ общей памяти. Зато бесплатно, приватно и — после пары часов мата — стабильно.
Теги: #llm #ollama #rocm #selfhosting

