Когда одинаковых коробок с unified memory две, первый инстинкт — разложить нагрузку поровну: сервисы туда и сюда, модели туда и сюда. Мы сделали наоборот. Вся платформа целиком живёт на одной ноде, а вторая обслуживает одну модель и в остальном стоит пустой. Одна грязная, одна чистая — и это не эстетика, а требование методики.
Что где живёт
Грязная нода — это весь стек: Dify, RAGFlow со своей свитой из MySQL, Elasticsearch и MinIO, векторная база, эмбеддинги и реранкинг на встроенном GPU, мониторинг, реверс-прокси и автоматизация по краям. На момент лонгрида на ней крутилось 34 контейнера. Тяжёлую генерацию эта коробка не делает: большие модели отвечают по локальной сети с другого железа.
Чистая нода — один сервер llama.cpp на Vulkan с одной MoE-моделью Qwen3.6. Больше на ней нет ничего: ни баз, ни прокси, ни дашбордов. Между замерами она почти простаивает — сознательно.
Почему чистой ноде нельзя иначе
Наш харнесс не верит на слово, что хост был пуст, — он это проверяет. Каждый прогон начинается с инвентаризации хоста: полный список живых контейнеров. В конце прогона инвентаризация снимается ещё раз, и оба снимка уходят в манифест как улика. Если в любом из двух снимков нашёлся GPU-способный сосед — что-то похожее на второй инференс-сервер или GPU-runtime, — ячейка бракуется целиком. Сосед, появившийся посреди прогона, убивает замер так же, как сосед, стоявший с самого начала.
На unified memory это не перестраховка: отдельного VRAM здесь нет, и любой сосед сидит на той же полосе памяти, через которую декодирует модель. Логика та же, что во всей нашей методике бенчмарков: условие, способное обесценить число, должно проверяться машиной, а не обещаться в тексте. А когда «на хосте больше ничего нет» — жёсткий гейт, дешевле всего проходить его второй машиной, где живёт всё остальное. Грязная нода существует, чтобы чистая могла быть пустой.
Три урока с грязной ноды
Версии фиксируются набором. Рабочее сочетание ядра, прошивки и драйвера на этом GPU-семействе — именно сочетание; безобидное на вид обновление одного элемента уже приносило регрессии.
Штатный мониторинг молчит. Фирменная GPU-утилита отвечает N/A по ключевым датчикам, поэтому температуру и питание мы читаем прямо из hwmon маленьким коллектором. Та же болезнь, что мы разбирали на совсем другом железе: зелёный пустой дашборд и скучное лекарство.
GPU-оффлоуд умеет исчезать молча. Неверно названный Vulkan ICD-манифест отключает GPU без единой ошибки, и генерация тихо едет на CPU. Верить можно только строке в логе рантайма про выгруженные на GPU слои — поэтому харнесс бракует и обнаруженный CPU-фолбэк.
Полная история — конфигурации, тюнинг памяти под GTT, замеры эмбеддингов и инференса, честный список нерешённого — в лонгриде на Habr. Эта страница — короткая карта; первоисточник там.