Перейти к содержанию
Публикация AiManual

Запуск MoE-модели на 12 ГБ VRAM: как Betelgeuse ускоряет prefill через out-of-core подгрузку экспертов

Разбираем три механизма Betelgeuse (bel-cli/bel-server), которые поднимают warm prompt processing крупной MoE-модели с 3-6 до 61,80 tok/s на RTX 3060 12 ГБ и 16

Коротко

Что будет в материале

  1. 01

    Что такое out-of-core MoE и почему модель на сотни гигабайт стартует на 12 ГБ VRAM

  2. 02

    Три механизма Betelgeuse, которые ускоряют prefill

  3. 03

    Какие цифры заявлены и как их правильно читать

  4. 04

    Betelgeuse против Strata: что на самом деле показывает сравнение

MoE-модель с 305,6 ГБ экспертных весов запускается на видеокарте с 12 ГБ VRAM потому, что на каждый токен активируется лишь малая часть экспертов. Остальное лежит на NVMe и читается по требованию. Проект Betelgeuse (bel-cli/bel-server) добавил к этой схеме три механизма против простоя GPU на prefill: кэш с фиксированными слотами, layer-major обработку промпта батчами по 16 токенов и перенос самых востребованных экспертов в VRAM по итогам первого прохода. По данным автора проекта, warm prompt processing вырос с 3-6 до 61,80 tok/s при декодировании 18,15-18,92 tok/s на RTX 3060 12 ГБ и 16 ГБ одноканальной DDR4-3200 в отчёте на r/LocalLLaMA.

Сразу о рамке доверия: ниже разобраны заявления одного энтузиаста на одной конфигурации. Независимого воспроизведения этих цифр нет, а таблица в исходном отчёте местами обрывается. Материал полезен как разбор инженерных приёмов, а не как готовый бенчмарк для выбора движка.

Что такое out-of-core MoE и почему модель на сотни гигабайт стартует на 12 ГБ VRAM

Out-of-core inference означает, что веса не помещаются в VRAM и оперативную память одновременно. Движок держит на устройстве рабочий набор, а остальное лежит на диске и подчитывается по ходу работы. Для плотной модели такой режим бесполезен: каждый токен требует все веса, и чтение превращается в бесконечную подкачку. У MoE на каждом слое работает роутер, который выбирает несколько экспертов из десятков, поэтому за один токен нужна небольшая доля матриц.

Отсюда и цифры теста: DeepSeek V4.1 Flash Q8_XL, который автор описывает как 305,6 + 110,6 ГБ, крутится на RTX 3060 12 ГБ с 16 ГБ одноканальной DDR4-3200 и PCIe 4.0 NVMe под CachyOS/Arch Linux. Тест шёл в cgroup с жёстким лимитом MemoryMax=12G и с 0B swap. Экспертный бэкбон взят в Q8_XL, рядом работает Engram-таблица в IQ4_NL, которая набирает 72,3 на бенчмарке DeepSWE.

Лимит памяти здесь не декорация. При 16 ГБ физической RAM и MemoryMax=12G у системы остаётся узкий коридор: страницы ядра, драйвер CUDA, кэш файловой системы и сам процесс инференса делят одни и те же гигабайты. Swap выключен, значит любая ошибка в раскладке буферов заканчивается не замедлением, а убийством процесса.

Prefill и decode: две разные бутылочные горлышка

Prefill обрабатывает промпт целиком. Токенов много, вычисления хорошо ложатся на матричные блоки, но набор нужных экспертов получается широким: разные токены промпта попадают в разные эксперты. Автор пишет, что промпт активирует почти каждого эксперта во всех 40 слоях модели. Значит prefill упирается не в математику, а в то, как быстро эксперты доезжают до вычислителя: шина PCIe, чтение с NVMe, пропускная способность RAM.

Decode работает иначе. На шаге генерируется один токен, набор активных экспертов узкий, зато шаг повторяется сотни раз. Здесь решают латентность чтения и пропускная способность памяти на каждый токен. Поэтому метрики в отчёте разделены: warm prompt processing (PP) отдельно, warm decode (TG) отдельно. Из этого же следует, что приёмы для prefill почти не меняют decode, и наоборот.

Цена провала prefill хорошо видна на бытовом примере из отчёта: промпт на 500 токенов, движок молотит на 1-3 tok/s и выдаёт первый токен через 30-60 секунд. Для чата это терпимо, для агентной работы с длинным контекстом невыносимо. Кто хочет сравнить с другим лагерем решений, может посмотреть разбор стриминга весов с SSD на примере Qwen3.8-Flash-Next 177B на RTX 5060 Ti 16 ГБ, там та же проблема решается через GCLOCK-кэш и lookahead-префетч.

Почему Engram table на 110 ГБ не съедает RAM

Логичный вопрос: как 110 ГБ файл может стоить почти ноль байт оперативной памяти. Механизм, описанный автором, такой: таблица целиком остаётся на NVMe, потому что активируется только на слоях 1 и 14. На один токен затрагивается около 48 строк общим объёмом примерно 192 КБ, и эти строки стейджатся в буфер VRAM размером 2 МБ в момент t=0. Глубина активации маленькая, поэтому файл не попадает в RAM и не вызывает CPU graph splits.

Это описание автора, а не измерение RSS сторонним инструментом. Механизм правдоподобен, но проверять его стоит самостоятельно, если планируете похожую раскладку на своей машине.

Три механизма Betelgeuse, которые ускоряют prefill

Все три приёма бьют в одну проблему: эксперты слишком медленно попадают в вычисление, и GPU простаивает, пока шина задыхается. По отдельности эффект каждого в отчёте не измерен, есть только суммарный результат.

Location-Invariant Cache Partitioning: 5 слотов в VRAM и 15 в RAM на слой

Движок держит 20 резидентных слотов на каждый слой: 5 «горячих» в VRAM и 15 в host-RAM, с жёсткой неинтерферирующей маршрутизацией. Смысл в предсказуемости. Когда эксперт закреплён за конкретным слотом, маршрутизация не перетасовывает размещение на каждом шаге, промахов становится меньше, а лишние чтения с диска не съедают бюджет времени.

С этим механизмом связано наблюдение автора: после прогрева кэша чтения с диска падают почти до нуля. Причина приземлённая: нужные эксперты уже лежат в слотах VRAM и RAM, повторный проход по тем же данным не ходит на NVMe.

Single-Pass Layer-Major Prefill: батчи по 16 токенов вместо микро-батчей по 3

Стандартный путь нарезки промпта на микро-батчи по 3 токена убивает занятость тензорных ядер: работы слишком мало, чтобы загрузить вычислитель. Betelgeuse идёт одним проходом в layer-major порядке, обрабатывая слой за слоем полными 16-токенными подбатчами. Активные эксперты из host-RAM в это время параллельно стримятся в execution ring по PCIe прямо во время счёта.

Ключевой момент здесь в перекрытии: передача и вычисление идут одновременно, а не по очереди. Второй эффект layer-major порядка в том, что движок заранее знает, какие эксперты понадобятся на текущем слое для всей пачки токенов, и может собрать их одним пакетом вместо десятков мелких запросов.

End-of-Pass Physical VRAM Consolidation: топ-5 экспертов переезжают в VRAM

В конце первого прохода движок смотрит, какие эксперты реально понадобились промпту и ранней генерации, и физически переносит пять самых активных в горячие слоты VRAM. Логическая траектория маршрутизации модели при этом не меняется: меняется только физическое размещение весов. Именно поэтому warm-прогон заметно быстрее холодного, а качество вывода не должно деградировать.

Честная оговорка по разделу: три механизма описаны автором как единый пакет изменений. Сколько даёт каждый по отдельности, из отчёта не следует.

Какие цифры заявлены и как их правильно читать

Все значения ниже взяты из публикации автора Betelgeuse и не проверены третьей стороной (первоисточник).

МетрикаЗначение по данным автора
Warm prompt processing (PP)61,80 tok/s, до изменений было 3-6 tok/s
Warm decode (TG)18,15-18,92 tok/s
Пик декодирования27,92 tok/s
Декодирование в агентной работе24,22 tok/s
TTFT на стандартных промптахпрактически мгновенный
Чтения с диска после прогрева кэшаблизко к 0%

Читать таблицу стоит как отчёт об одном эксперименте. Один энтузиаст, одна машина, конкретная сборка на sm_86, cgroup с MemoryMax=12G, 0B swap, CachyOS/Arch. Любое из этих условий может сдвинуть результат: другой дистрибутив, другой NVMe, другой драйвер, другое квантование. Автор сам пишет, что текущая версия лучше всего работает на sm_86, а дополнительную оптимизацию обещает в следующих релизах.

Почему 0% чтений с диска это про кэш, а не про чудо

Нулевые чтения с NVMe означают, что рабочий набор промпта уже разложен по слотам VRAM и host-RAM. Как только меняется домен промпта, маршрутизация уводит токены к другим экспертам, слоты промахиваются, и чтения возвращаются. Метрика описывает прогретый повторный прогон по похожим данным, а не устойчивое состояние движка на произвольной нагрузке. В исходной таблице отчёта, к тому же, часть строк про холодное чтение с SSD обрезана, так что полную картину холодного старта по ней не собрать.

Betelgeuse против Strata: что на самом деле показывает сравнение

В отчёте есть таблица, где Betelgeuse сопоставлен со Strata. У Betelgeuse конфигурация RTX 3060 12 ГБ и 16 ГБ RAM. У Strata набор шире: RTX 5070 12 ГБ, RTX 3060 12 ГБ и сборка из 4× R9700, с 64 ГБ RAM на RTX 5070 и 46 ГБ на RTX 3060.

КонфигурацияWarm prompt processingWarm decode
Betelgeuse, RTX 3060 12 ГБ, 16 ГБ RAM61,80 tok/s18,15-18,92 tok/s
Strata, RTX 3060 12 ГБ, 46-64 ГБ RAM149 tok/s (8K)8-10 tok/s
Strata, RTX 5070 12 ГБ121 tok/s (4K) - 231 tok/s (8K)4,7 tok/s

Формально выходит, что по prefill Strata быстрее, а по декодированию Betelgeuse выигрывает. Тянуть из этого вывод «движок А лучше движка Б» нельзя, и вот почему.

Почему сравнение не эквивалентно

Сравниваются разные модели и квантования. Betelgeuse гоняет Q8_XL-бэкбон с Engram-таблицей IQ4_NL, то есть высокую точность. По утверждению автора, Strata в его таблице работает с Qwen 3.8 Flash Next в IQ2_XS. Разница в точности квантования сама по себе меняет и объём чтений, и скорость, поэтому tok/s перестают быть мерой качества движка.

Второй разрыв в объёме RAM: 16 ГБ против 46-64 ГБ. Держать больше экспертов в памяти при 64 ГБ заметно проще, и это преимущество железа, а не софта. Третий разрыв в GPU: RTX 5070 и связка из четырёх R9700 несопоставимы с одной RTX 3060. Сравнение имело бы смысл при одной модели, одном квантовании и одинаковом объёме памяти.

Отдельно стоит оценить риторику. Фразу автора Betelgeuse про «урезанную» модель у конкурента нельзя воспринимать как измерение, это полемика. Что реально проверяемо: квантование, объём RAM, конкретные цифры PP и TG. Про сам движок Strata и его поведение на 12 ГБ VRAM есть отдельный разбор замеров на контексте 128K и требований к памяти для Q2_0, IQ2_XS и IQ3_XXS.

Ограничения 16 ГБ одноканальной DDR4-3200 и почему двухканал важен для prefill

Один канал DDR4-3200 даёт 3200 MT/s × 8 байт, то есть около 25,6 ГБ/с теоретического максимума. Два канала удваивают эту планку. Пятнадцать host-RAM слотов на слой и стриминг экспертов в execution ring живут ровно на этой пропускной способности, поэтому prefill чувствителен к режиму памяти куда сильнее, чем decode.

Автор оценивает, что переход на двухканальные 16 ГБ поднимет prompt processing с 61 до 120 tok/s. Это прогноз, а не замер: в отчёте нет строки с результатом на двухканальной конфигурации. Похожий эффект он уже показывал раньше на другой модели: в разборе IQ4_XS на RTX 3060 12 ГБ и 16 ГБ RAM вышло 14,0 tok/s в одноканальном режиме и 24,0 tok/s в двухканальном, и там это подкреплено механикой host-RAM victim cache с асинхронным DMA.

Жёсткий лимит MemoryMax=12G и 0B swap при 16 ГБ RAM означает, что запас памяти минимальный. Двухканальный комплект из двух планок по 8 ГБ даст ту же ёмкость и удвоенную пропускную способность, но не увеличит объём: раскладка слотов останется такой же тесной.

Где ещё упрётся, даже если добавить канал памяти

PCIe 4.0 NVMe имеет собственный потолок, а латентность чтения и нагрев накопителя добавляют разброс. Кэш на 20 слотов в слое конечен: при маршрутизации, которая уводит токены к редким экспертам, промахи будут упираться в диск, и второй канал RAM тут не поможет. Латентность чтения тоже не лечится шириной шины. Практический вывод: двухканал снимает часть давления, но упор может сместиться в NVMe, и гарантии «два икса» он не даёт.

Кому этот сценарий имеет смысл, а кому проще взять больше VRAM

Сценарий Betelgeuse рассчитан на конкретную ситуацию: RTX 3060 12 ГБ уже есть, NVMe есть, хочется запускать крупную MoE-модель в высоком квантовании, а бюджет на новое железо ограничен. Готовность возиться с Linux, cgroup и сборкой обязательна, потому что весь выигрыш держится на аккуратной настройке окружения.

Обратная сторона: скорость после прогрева кэша зависит от того, насколько новый промпт похож на предыдущие. Продакшн-нагрузка с разнообразными запросами и длинным контекстом будет регулярно промахиваться по слотам. Если нужна предсказуемая скорость на любых промптах, больше VRAM или RAM даст более ровный результат, чем тонкая настройка out-of-core движка.

Для сравнения масштабов: на RTX 5090 с 64 ГБ DDR5 пользователь получил около 10 токенов в секунду на DeepSeek V4.1 Flash 8K, о чём есть отдельный разбор с экономикой против API. Цифры на бюджетной карте из отчёта Betelgeuse выше по декодированию, но получены на другой модели, другом квантовании и другом движке, так что это иллюстрация разброса, а не рейтинг железа.

Как воспроизвести окружение без выдуманных команд

Что нужно подготовить по описанию автора:

  • bel-cli и bel-server из проекта Betelgeuse, сборка под CUDA и архитектуру sm_86;
  • CachyOS или Arch Linux, тест шёл именно на этой связке;
  • cgroup с MemoryMax=12G, чтобы процесс не вылез за отведённый лимит;
  • полностью отключённый swap, автор указывает 0B;
  • PCIe 4.0 NVMe как хранилище весов и Engram-таблицы;
  • GPU уровня RTX 3060 12 ГБ.

Конкретные команды запуска и флаги здесь не приводятся намеренно: в исходном отчёте их нет, а придумывать синтаксис чужого CLI смысла ноль. Актуальные параметры смотрите в репозитории проекта, там же стоит сверить поддержку вашей архитектуры GPU.

Что в итоге: инженерная идея сильная, но цифры из одного отчёта

Три механизма Betelgeuse решают реальную проблему: при out-of-core MoE GPU простаивает, пока эксперты едут по шине. Кэш с фиксированными слотами убирает хаос размещения, layer-major prefill батчами по 16 токенов перекрывает передачу с вычислением, консолидация VRAM в конце прохода переносит горячие эксперты туда, где они нужнее всего. Как инженерный разбор это ценно независимо от точных цифр.

Сами цифры такие: warm PP с 3-6 до 61,80 tok/s, warm decode 18,15-18,92 tok/s, пик 27,92 tok/s. Всё это получено одним энтузиастом на RTX 3060 12 ГБ с 16 ГБ одноканальной DDR4-3200, PCIe 4.0 NVMe, под CachyOS/Arch с MemoryMax=12G и без swap. Независимой проверки нет.

Сравнение со Strata приведено по таблице автора и неэквивалентно по модели, квантованию и объёму RAM, поэтому переносить его на выбор инструмента нельзя. Обещание удвоения prefill от двухканальной памяти остаётся оценкой автора.

Практический шаг, если конфигурация совпадает с описанной: открыть репозиторий Betelgeuse, проверить поддержку sm_86 и собрать окружение с лимитом cgroup и без swap. Если же ключевое требование - стабильная скорость на произвольных промптах, считать бюджет на карту с большим объёмом VRAM будет рациональнее, чем растягивать 12 ГБ слотами кэша.

Подписаться на канал