← Лендинг Hermes Agent

Опубликовано

EXL3-2: тысяча квантов, один подходит. Учимся считать бюджет до закачки

Автор: Гусев Николай [портфолио]

Обновлено

Темы: llm, exllamav3, quantization, moe, vram, nvme

Джилл с шишкой сидит под полкой среди рассыпанных квантов, грызёт ручку

В первой части я похоронил ExLlamaV3 на 8 ГБ: релиз с кодбуком mcg молча не выгружает экспертов, и 35B MoE падает по памяти. Обещал продолжение - вот оно. Проверил кодбуки у живых релизов, нашёл правильный, скачал, запустил. Offload заработал. А потом посчитал бюджет и понял, что зря качал. Разбираю обе ошибки: свою и ту, которую совершит каждый, кто повторит мой путь.

Считаем кодбуки каталога

Первым делом - сколько вообще EXL3-релизов живых. Поиск HuggingFace отдаёт больше тысячи репозиториев, но у большинства скачиваний меньше сотни - это мёртвый груз. Оставил 223 живых (от 100 скачиваний) и вытащил из каждого quantization_config.json скриптом с 12 потоков, весь обход занял 13 секунд.

Расклад кодбуков: 124 релиза mul1, 31 mcg, 68 без явного поля. То есть mcg-модель из первой части попала в меньшинство - большинство живых релизов совместимы с CPU-offload. Но кодбук - только первый фильтр. Второй - архитектура: выгружать можно только routed-экспертов MoE, у плотных моделей выгружать нечего. Третий - размер против твоего бюджета памяти. Все три фильтра должны сойтись одновременно, и ни один из них не написан в карточке модели.

Сведение: mul1 плюс MoE-архитектура дали 14 релизов. Из них четырнадцати ровно один проходит третий фильтр для машины класса 8 ГБ VRAM и 32 ГБ RAM - Ornith-1.5-35B-A3B в 4bpw от ultimatechris, 18.4 ГиБ. Его я и скачал.

Проверка offload на живом релизе

Кодбук нового релиза проверил до закачки, на уровне тензоров:

кодбук: mul1, формат 1.4.4
тензоры эксперта: .suh, .svh, .mul1
(для сравнения: mcg-модель из первой части - .mcg, 30971 штуки, ноль .mul1)

При загрузке движок ищет у эксперта тензор .mul1 и регистрирует слой на выгрузку только если находит. Здесь он находил на каждом слое. Флаг -mcl 40 выгрузил 40 слоёв из 48 на отдельный рабочий процесс, ни одного skipped, воркер поднялся на шести потоках с AVX-512 и VBMI. Фича, которая молча не работала в первой части, здесь заработала полностью.

Попутные грабли API, которые стоят абзаца: кэш нужно создавать до загрузки модели, токенизатор - от конфига, а не от модели, и Generator принимает все три аргумента. Ни одна из этих вещей не описана в README движка - только в исходниках.

Бюджет, который надо было посчитать до закачки

Теперь про ошибку. Ornith-1.5 - это 48 MoE-слоёв, и почти весь его вес - routed-эксперты. Чтобы выгрузка имела смысл, эксперты должны лежать в связке VRAM плюс RAM целиком, без остатка в файле подкачки.

Считаем: 18.4 ГиБ весов плюс пара гигабайт на активации против бюджета машины. У меня свободно было 6.8 ГиБ VRAM и около 17 ГиБ RAM, минус система остаётся примерно 16 ГиБ usable. Дефицит - около 5 ГиБ: четверть экспертов обречена жить в pagefile.

Что делает дефицит при генерации. На каждый токен модели нужны 8 активных экспертов из каждого MoE-слоя - суммарно около 460 МиБ весов за токен. Нужный эксперт в RAM - чтение мгновенное. Вытеснен в pagefile - страница читается с SSD. Чем больше дефицит, тем выше доля экспертов на диске: каждый недостающий гигабайт добавляет примерно 27 МиБ чтения с SSD на каждый токен. При нашем дефиците это порядка 118 МиБ за токен, и генерация на глазах превращается в слайд-шоу.

Эта арифметика заняла бы две минуты до закачки. Вместо этого я скачал 18.4 ГиБ, загрузил модель, погонял генерацию - CPU-воркер пахал в полную силу два с половиной часа, система жила на полутора гигабайтах свободной памяти, а NVMe прочитала сотни гигабайт ради нескольких сотен токенов. Арифметика предсказала это до скачивания. Я её не сделал - увлёкся проверкой кодбука и пропустил проверку бюджета.

Кстати о цене: час такой генерации - порядка 30 ГиБ чтения с накопителя. Это не "медленно", это износ SSD ради нуля пользы.

Что всё это значит

Правильный порядок вопросов при выборе EXL3-релиза такой. Первый вопрос - кодбук: mul1 или mcg, curl одной строкой, mul1 открывает offload. Второй - архитектура: MoE или плотная, у плотной выгружать нечего. Третий, и самый главный, - бюджет: гигабайты экспертов против гигабайт твоей памяти с запасом на систему. Дефицит в гигабайт - это уже десятки секунд на токен и мёртвый SSD.

На моём железе 8 ГБ VRAM и 32 ГБ RAM этой модели места нет, и никакой движок это не изменит. На двух 5080 владельца сервера из первого материала - другое дело: 32 ГиБ VRAM против 18.4 ГиБ весов, offload почти не нужен, всё живёт на видеокартах. Та же модель, тот же движок, другой бюджет - другая вселенная.

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

Альтернатива, которая делает это правильно

Схема "эксперты на быстром NVMe" существует в виде отдельных движков, и мы о них уже писали. Colibri - один C-файл без зависимостей, заточенный ровно под этот сценарий: плотная часть модели живёт в RAM постоянно, routed-эксперты лежат на NVMe и читаются асинхронным чтением напрямую, минуя кэш страниц. Роутер предсказывает следующих экспертов с точностью около 71 процента и подгружает их параллельно с вычислениями, горячие эксперты держатся в LRU-кэше, история обращений сохраняется между запусками - при втором старте горячие слои уже на месте.

Замеры из нашего сентябрьского материала: от 0.05 токена в секунду на ноутбуке с холодным кэшем до 5.8-6.8 на станции с шестью 5090. Отличие от подхода ExLlamaV3 принципиальное: у ExLlamaV3 выгрузка - это своп вытесненных страниц через файл подкачки операционной системы, со всеми издержками пейджинга. У Colibri диск - первоклассный тир хранения с прямым доступом, предвыборкой и своей политикой кэша. За это отвечают архитектура, а не удача.

Практическое правило из того материала работает и здесь: если у тебя 64 и больше гигабайт VRAM при 32 гигабайтах RAM и NVIDIA - смотрите в сторону FreeToken, если та же 32 ГБ RAM и меньше видеопамяти - Colibri. ExLlamaV3 с CPU-выгрузкой хорош там, где offload нужен на пару слоёв, а не как основной способ существования модели.

Кандидаты под разные видеокарты

По итогам скана каталога собрал таблицу живых mul1 и MoE релизов, которые влезают в связку 32 ГБ RAM с видеокартой от 12 ГБ. Считал по формуле из середины статьи: веса плюс два гигабайта активаций против VRAM плюс 24 гигабайта usable RAM минус три на кэш и прослойки.

Кандидаты mul1 + MoE при 32 ГБ RAM:

модель / релиз                                      веса   bpw   VRAM
Ornith-1.5-35B-A3B-EXL3 (ultimatechris)             18.4   4.0   12/16/24
K2-Horizon-MoVA-36B-A4B-exl3 (pirola)               19.1   4.1   12/16/24
Nex-N2.5-mini-exl3 (auryn-macmillan)                22.2   5.1   12/16/24
KAT-Coder-V2.5-Dev-MTP-exl3 (P4pps3n)               22.3   5.1   12/16/24

(веса в ГиБ; VRAM - минимальная карта, на которой всё помещается
без свопа при 32 ГБ RAM; полный HuggingFace-путь в скане каталога)

Все четыре проходят бюджет 12 ГБ VRAM с запасом - при 12 ГиБ карты на CPU уедет от 8 до 12 ГиБ экспертов, что помещается в RAM без свопа. Это уже рабочая конфигурация, в отличие от моей. Больше 24 ГБ VRAM при 32 ГБ RAM расширяет список слабо - упор уходит в RAM, а не в видеокарту.

Кандидаты mul1 и MoE при 64 ГБ RAM

Удваиваем память - каталог открывается заново. При 64 ГБ RAM usable около 56 ГиБ, и к списку добавляются восемь тяжёлых релизов Flash-Next и её производных:

модель / релиз                                       веса   bpw   VRAM
Flash-Next-EXL3-2.50bpw Abliterated (ghost-actual)   60.0   2.5   24/48/80
Flash-Next-EXL3-2.50bpw (r0b0tlab)                   60.0   2.5   24/48/80
Flash-Next-Uncensored-exl3-3bpw (Lygodactylus)       67.3   3.0   24/48/80
Flash-Next-exl3-3.05bpw-heretic (andrevp)            79.2   3.05  48/80
Flash-Next-exl3-3.50bpw_hq_h6_ng6 (groxaxo)          92.3   3.5   48/80
Swift1.5-Qwen3.8-Flash-Next-EXL3 (KatterMobile)     100.0   4.05  80
Flash-Next-Uncensored-exl3-4bpw (Lygodactylus)      101.5   4.05  80

(веса в ГиБ; VRAM - минимальная карта для работы без свопа
при 64 ГБ RAM; 397B Орнит на 166 ГиБ - за рамками даже этого)

Для 125B Flash-Next это уже полноценные варианты: 2.50bpw влезает на одну 24-гиговую карту с выгрузкой пары слоёв, 3.05bpw heretic - на две по 24. При 80 ГиБ VRAM весь релиз живёт на видеокартах, и CPU-offload превращается в запасной выход, а не в способ существования.

Остальные mul1-MoE релизы (Nex-N2.5, KAT-Coder из первой таблицы плюс два десятка менее популярных) - в скане каталога. Ссылки на все - в скане каталога.

Сервер для ExLlamaV3 - TabbyAPI: OpenAI-совместимый API, управление моделями, работает с EXL3 нативно.

Харнесс для повторения

Весь код из обеих частей лежит в репозитории канала, папка harness: сканер каталога с параллельным обходом (223 репозитория за 13 секунд), скрипт проверки кодбука одной строкой, по-токенный бенчмарк с таймингом фаз и результат скана на дату публикации. Ссылки: GitHub - NikolayGusev-astra/channel-materials, папка 2026-10-03-ornith-35b-home-server/harness.