mysurik.ru

ComfyUI на CPU: как я бросил GPU и обрёл покой

ComfyUI на CPU как я бросил GPU и обрёл покой

Когда я задумал запустить генерацию картинок на своём сервере, логичным выбором казалась старая RX 580. В теории — отличная карта для Stable Diffusion: 8GB VRAM, шина 256-bit, сообщество уверяло, что она летает. На практике всё пошло не так.

Попытка №1: ROCm

AMD продвигает ROCm как свой ответ CUDA. Разворачиваю rocm/pytorch — контейнер падает при первой же попытке загрузить модель. Ошибки вида Missing HIP kernel. Лезу в форумы — оказывается, для Polaris (RX 580, gfx803) поддержка в ROCm урезана.

Дальше — перебор образов:

  • rocm/pytorch:latest — не видит GPU
  • rocm/pytorch:rocm6.1 — видит, но падает на forward pass
  • woodrex/rocm612-torch24-gfx803 — самый многообещающий: собран специально под gfx803, GPU детектится, но генерация хенгует

Последний образ заслуживает отдельного упоминания. Он единственный, кто прошёл инициализацию и даже начал денойзинг. На третьем шаге — тишина. docker logs молчит, процессов нет, контейнер жив. Просто берёт и зависает без единой ошибки.

Я потратил два дня на перебор hipBLAS, rocBLAS, MIOpen разных версий. Результат — ноль.

Попытка №2: CPU mode

Решение пришло от безнадёги: --force-cpu. ComfyUI запустился. Первая картинка за 4 минуты на 320×320. Это медленно, но оно работает.

Дальше — оптимизация. Собрал свой образ на python:3.10-slim:

FROM python:3.10-slim

WORKDIR /app
RUN apt-get update && apt-get install -y git && 
    git clone https://github.com/comfyanonymous/ComfyUI && 
    cd ComfyUI && 
    pip install --no-cache-dir -r requirements.txt torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu

CMD ["python", "main.py", "--listen", "0.0.0.0", "--port", "8188"]

Он весит ~3.5GB, запускается за 20 секунд, не требует GPU-драйверов, не ругается на HIP, не виснет.

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

Замеры на реальном железе (Proxmox хост, CPU — без GPU-ускорения):

Разрешение Steps Время на шаг Итого
320×320 10 ~6 сек ~1 мин
512×512 20 ~15 сек ~5 мин
768×768 30 ~25-35 сек ~15 мин

Для блога — терпимо. Для продакшна — нет. Но если GPU нет или он не поддерживается — CPU работает.

Что пошло не так с ROCm?

  1. gfx803 — устаревшая архитектура. ROCm 6+ официально её не поддерживает. Нативные образы от сообщества — лотерея.
  2. Docker + GPU — добавляет уровень абстракции, на котором сыпется ещё больше. Нужен --device /dev/kfd, --group-add video, совпадение версий драйвера хоста и библиотек в контейнере.
  3. Отсутствие обратной связи — когда GPU хенгует, нет никакого сообщения об ошибке. Просто пустой лог.

Что в итоге

CPU-режим — это честно. Медленно, стабильно, предсказуемо. Никакой магии, просто числа.

Я оставил Dreamshaper 8 (SD 1.5) как основную модель — она даёт хороший баланс качества и скорости. Контейнер запущен с --restart unless-stopped, интегрирован в WordPress через плагин-обёртку.

Мораль: если у вас нет современного NVIDIA или нормального AMD (RX 7000+), не мучайтесь. CPU — норм. Картинки генерируются, пост пишется, сервер не дымится.

Я расскажу подробнее всю эту историю с RX 580 и ROCm, потому что за сухим перечислением ошибок скрывается целый квест, из которого я вынес немало полезного. Если ты собираешься крутить Stable Diffusion на сервере без современной NVIDIA — эта статья сэкономит тебе дни, которые я потратил.

С чего всё началось. У меня была старая RX 580 с 8 гигабайтами видеопамяти, которая лежала без дела. В интернете полно роликов «RX 580 летает для Stable Diffusion», и я повёлся. Ключевая деталь, которую все почему-то опускают: «летает» — это на Windows с DirectML или с определёнными сборками, а в линуксовом Docker с ROCm всё куда мрачнее. AMD очень избирательно относится к поддержке своих старых карт в ROCm, и RX 580 относится к архитектуре Polaris, которую новые версии ROCm практически бросили.

Первая моя ошибка была в том, что я взял самый свежий официальный образ rocm/pytorch. Он вообще не видел GPU — при старте просто писал, что устройств нет. Потом я выяснил, что нужно прокидывать внутрь контейнера устройства /dev/kfd и /dev/dri, добавлять пользователя в группу video, задавать переменные окружения вроде HSA_OVERRIDE_GFX_VERSION. Без этого ROCm просто не поднимается. Когда я всё это сделал, образ rocm6.1 начал видеть карту, но падал на forward pass с непонятными ошибками вида Missing HIP kernel. Каждая такая ошибка уводила меня на форумы, где кто-то когда-то решал похожую проблему другой версией драйвера.

Самое обидное было с образом от сообщества woodrex, который специально собран под gfx803. Он прошёл инициализацию, загрузил модель, начал денойзинг — и просто завис на третьем шаге. Без ошибок, без падений, без логов. Контейнер жив, процессы исчезли, тишина. Я перепробовал разные версии hipBLAS, rocBLAS, MIOpen, менял переменные окружения, пересобирал — результат нулевой. Такое зависание без обратной связи — худшее, что может быть при отладке, потому что ты не знаешь, в какую сторону копать.

После двух дней таких плясок я сдался и включил CPU-режим. И тут произошло неожиданное: вместо разочарования я получил рабочую систему, пусть и медленную. Первая картинка 320×320 пришла за четыре минуты. Для блога это терпимо: запустил генерацию, пошёл писать текст, вернулся — картинка готова. Не для продакшна, конечно, но для своих задач — вполне.

Отдельно хочу остановиться на Docker-образе, который я собрал. Ключевая деталь — ставить CPU-сборку PyTorch через —index-url https://download.pytorch.org/whl/cpu. Это избавляет от кучи проблем: образ не тащит CUDA- или ROCm-библиотеки, не требует драйверов, весит меньше и запускается быстрее. Мой образ на базе python:3.10-slim весит около 3.5 гигабайт и стартует за двадцать секунд. Никаких HIP, никаких /dev/kfd, никакой магии — просто рабочий инструмент.

Теперь про цифры производительности, чтобы ты понимал, чего ожидать. На моём CPU в проксмоксе: 320×320 при десяти шагах — около минуты суммарно; 512×512 при двадцати шагах — около пяти минут; 768×768 при тридцати шагах — около пятнадцати минут. Скорость на шаг зависит от мощности процессора и количества потоков, так что у тебя цифры могут отличаться в обе стороны. Главное — прикинь заранее, подходит ли тебе такой темп.

Что я понял про выбор модели. Для CPU-режима важно брать лёгкие модели. Я остановился на Dreamshaper 8, который построен на базе SD 1.5, — он даёт хороший баланс качества и скорости и весит заметно меньше более тяжёлых моделей. Тяжёлая модель на CPU может превратить и так медленную генерацию в пытку. Правило простое: чем меньше шагов и чем легче модель — тем быстрее результат.

Ещё несколько практических советов. Ограничь количество шагов до разумного минимума — для многих задач хватает 10–15. Уменьшай разрешение, если качество не критично, а потом масштабируй картинку. Держи под рукой команду для выгрузки модели между генерациями — это экономит память. И обязательно поставь restart: unless-stopped, чтобы контейнер поднимался сам после перезагрузки сервера. Мой контейнер так и работает, я про него забыл и просто пользуюсь.

Про интеграцию с WordPress расскажу пару слов. Я написал плагин-обёртку, который дергает ComfyUI через API. У ComfyUI есть HTTP-интерфейс: можно отправить workflow, дождаться завершения и забрать картинку. Это позволило мне генерировать изображения прямо из админки, не заходя в контейнер. Для блога — очень удобно: не нужно вручную выгружать картинки, всё делается одним движением.

Теперь про мораль, ради которой я вообще пишу этот текст. Если у тебя нет современной NVIDIA или нормальной AMD из семейства RX 7000+ — не мучайся с ускорением на старой видеокарте. Я потратил два дня на ROCm и получил ноль. Включил CPU-режим — и всё заработало за вечер. Да, медленно. Но стабильно и предсказуемо. Для задач уровня «сгенерировать обложку к посту» этого более чем достаточно.

И напоследок о том, что я бы сделал иначе, знай я всё это заранее. Я бы сразу проверил, поддерживает ли моя видеокарта ROCm нужной версии — это час, а не два дня. Потом, если не поддерживает — сразу собрал бы CPU-образ и не тратил время на эксперименты с драйверами. И я бы не верил слепо роликам «RX 580 летает» — в них почти всегда опускают детали про операционную систему, драйверы и контейнеры.

Сейчас мой сервер спокойно генерирует картинки на CPU, пост пишется, и ничего не дымится. Может, когда-нибудь я куплю карту посовременнее и ускорюсь — но в том, что уже есть, я нашёл рабочее решение. Главный урок этой истории: иногда путь назад, к простому и скучному CPU-режиму, — это самый быстрый путь вперёд к результату.

Расскажу ещё про несколько хитростей, которые я открыл уже после того, как запустил CPU-режим. Во-первых, очень полезно посмотреть, сколько ядер доступно контейнеру, и при необходимости ограничить или, наоборот, разрешить больше потоков через настройки Docker. PyTorch по умолчанию использует столько потоков, сколько видит, и на хостинге с кучей виртуальных ядер это может привести к неожиданной нагрузке на соседей. Я выставил через переменную окружения разумное число потоков, чтобы генерация не мешала основному сайту.

Во-вторых, я заметил, что скорость зависит от того, что ещё происходит на сервере в момент генерации. Если параллельно идёт бэкап или другой тяжёлый процесс — время на шаг может вырасти в полтора-два раза. Поэтому я стараюсь гонять генерацию в спокойные часы, когда на сервере мало активности. Для моего блога это не критично, но если бы мне нужно было генерировать много картинок — я бы вынес ComfyUI на отдельную машину или как минимум выделил ему фиксированные ресурсы.

В-третьих, про сохранение модели в памяти. Между генерациями ComfyUI может выгружать модель, и загрузка заново занимает время. Если ты генерируешь серию картинок — постарайся держать модель в памяти, а не перезагружать её каждый раз. Сэкономишь минуты, а на CPU каждая минута на счету.

И последняя мелочь, которая кажется очевидной, но о ней легко забыть: сделай бэкап своих workflow. У меня был случай, когда я пересоздал контейнер и потерял все свои настроенные пайплайны. Хорошо, что я запомнил структуру и восстановил за полчаса, но могло быть хуже. ComfyUI хранит workflow прямо в интерфейсе, и их можно экспортировать в JSON — сделай это заранее.

Ваш комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *