Все статьи
Артемий Мазаев·· 8 мин чтения

MoE изнутри: как 17B активных бьют 70B плотных 🧠🎛️

Mixture-of-Experts изнутри: где живут эксперты, как роутер выбирает top-k, почему без load balancing всё коллапсирует и что такое top-k routing.

MoE изнутри: как 17B активных бьют 70B плотных 🧠🎛️

Ну чё, малютки, смотрите на цифры: Qwen3.5 — 397 миллиардов параметров, а токены строчит со скоростью модели на 17B. Kimi K2.5 — триллион параметров, активных — 32B. DeepSeek-V3 — 671B, работает как 37B. Что за читерство? Почему все флагманы опенсорса внезапно стали MoE — и почему при этом никто не разорился на видеокартах?

Я уже махал этим словом в четырёх статьях. Пора разобрать, что внутри.

🔥Суть за 10 секунд

В обычной модели каждый токен прогоняется через все параметры. В MoE жирную часть модели (FFN) нарезали на десятки «экспертов», и на каждый токен роутер включает только пару из них. Знания хранятся во всех параметрах, а вычисления на токен — только в активных. Платим памятью: жить в VRAM обязаны все эксперты.


Где в трансформере живёт MoE

Вспомним анатомию: трансформер — это стопка одинаковых блоков, в каждом — attention и FFN (feed-forward сеть, два здоровенных линейных слоя). Сюрприз для тех, кто не считал: примерно две трети параметров модели лежат именно в FFN — attention на его фоне лёгкий.

MoE меняет ровно одну вещь: вместо одного FFN в блоке — N маленьких FFN-экспертов плюс крошечный роутер. Attention не трогают, он остаётся плотным. Отсюда факт, который я уже проговаривал в статье про KV-кэш: у MoE-модели кэш считается как у обычной — разрежены только эксперты, а внимание работает по-старому.

1Токен проходит attention — как в обычной модели, плотно
2Роутер смотрит на hidden state и выбирает top-k экспертов из N
3Токен прогоняется только через выбранных — остальные N−k спят
4Их выходы складываются с весами роутера — это и есть выход слоя
Слева обычный блок: FFN один и считается весь. Справа MoE: attention не тронут, а вместо FFN — роутер и эксперты, из которых на токен работают двое.

Роутер: маленький слой с большой властью

Роутер звучит солидно, а на деле это один линейный слой: hidden state размерности d умножается на матрицу d×N — получается N чисел, по скору на эксперта. Дальше top-k (обычно от 2 у Mixtral до 8 у DeepSeek и Qwen), softmax по выжившим — и готовы веса для смешивания. Потыкай:

🎛️ Роутер выбирает top-2 из 8 экспертов
Для каждого токена роутер считает скоры по всем экспертам и включает двух лучших. Точки под экспертом — сколько токенов он уже обработал. Смотри, как похожие токены липнут к одним и тем же экспертам.
Функцияget_price()вернула42,анеnull!
E154%
слова
E2
морфемы
E3
пунктуация
E4
числа
E546%
код
E6
скобки
E7
общий
E8
???
Выход слоя = 54% × E1 + 46% × E5. Остальные шесть экспертов для этого токена не считаются вообще — их веса даже не читаются из памяти.
Токен 1/11

Ключевое в этой демке — подпись внизу: невыбранные эксперты не считаются вообще. Это не «посчитали и умножили на ноль», их веса даже не читаются из памяти. Вся экономия MoE стоит на этом факте — запомни его, он выстрелит в секции про скорость.

И заметь: выбор происходит на каждом токене в каждом слое заново. Один токен в 60-слойной модели с top-8 соберёт себе маршрут из ~480 экспертов — у соседнего токена маршрут будет другой.


Специализация: миф и реальность

Интуиция рисует красивую картину: вот эксперт по коду, вот по медицине, вот по стихам. Реальность скучнее и интереснее: когда исследователи (в том числе авторы Mixtral) посмотрели, кому роутер раздаёт токены, тематической специализации не нашли. Эксперты специализируются по токен-паттернам: этот любит пунктуацию, тот — числа, третий — отступы в коде и питоновские кейворды.

Почему так? Роутер видит не «тему документа», а hidden state конкретного токена — и кластеризует то, что видит. Синтаксис в этом представлении различим куда лучше, чем «медицина vs юриспруденция».

💡Shared experts: общага + специалисты

DeepSeek докрутил схему: помимо роутизируемых экспертов есть shared expert, который включён всегда, для каждого токена. Логика: базовые вещи (грамматика, частые слова) нужны всем — незачем заставлять каждого эксперта дублировать их у себя. Общее — в shared, частное — в роутизируемых, которых при этом можно нарезать мельче и больше (в DeepSeek-V3 их 256, активных 8+1). Эту же схему используют Qwen3.5 и Kimi.


Load balancing: главная головная боль MoE

А теперь причина, по которой MoE двадцать лет (идея из 1991 года!) не могли нормально завести. Роутер обучается вместе с моделью, и в этой системе есть петля положительной обратной связи: эксперт, которого выбирают чаще, больше учится → становится лучше → роутер выбирает его ещё чаще. Богатые богатеют, бедные умирают:

⚖️ Куда роутер отправляет токены
Доля токенов на каждого из 8 экспертов после обучения. Оранжевый — перегруз, серый — эксперт практически мёртв.
E1
11%
E2
4%
E3
41%
E4 💀
2%
E5
32%
E6 💀
1%
E7
9%
E8 💀
0%
3
Мёртвых экспертов
38%
Параметров выброшено зря
Классический коллапс: E3 и E5 тащат 73% трафика, три эксперта умерли. Их параметры лежат в VRAM мёртвым грузом — ты платишь памятью за ёмкость, которой нет.

Мёртвый эксперт — это выброшенные параметры: лежат в VRAM, есть не просят, но и пользы ноль. Ты хотел модель на 397B знаний, а получил на 150B с балластом. Чем это лечат:

1Auxiliary loss (Switch Transformer) — штраф за неравномерность: чем кривее распределение токенов по экспертам, тем больнее лоссу. Классика, но портит основную задачу: роутер иногда шлёт токен «не туда» ради ровной статистики
2Router z-loss (ST-MoE) — прижимает логиты роутера к нулю, чтобы тот не уходил в сверхуверенность и не разносил обучение численно
3Aux-loss-free (DeepSeek-V3) — хитрость: к скору каждого эксперта добавляется bias, который после каждого батча подкручивается — недогруженным плюс, перегруженным минус. Bias влияет только на выбор, не на веса смешивания — балансировка есть, порчи лосса нет

Отдельная пикантность: балансировать надо не только ради качества, но и ради железа — на серьёзном инференсе эксперты размазаны по разным GPU (expert parallelism), и перекошенный роутер превращает одну карту в бутылочное горлышко, пока остальные курят.


Математика: почему 17B бьют 70B

Теперь главный вопрос из заголовка. У модели два числа параметров, и они отвечают за разное:

  • Total (397B) — сколько знаний влезает в модель. Ёмкость.
  • Active (17B) — сколько вычислений тратится на токен. Цена.

Плотная модель жёстко связывает эти числа: хочешь больше знаний — плати больше компьюта на каждый токен, даже если для слова «привет» столько не нужно. MoE эту связь разрывает: знаний — на 397B, а платишь по 17B за токен. Эмпирическое правило большого пальца из практики: по качеству MoE ведёт себя примерно как плотная модель на √(total × active) — для Qwen3.5 это ~82B, для DeepSeek-V3 ~157B. Числа грубые, но порядок верный: 17B активных честно бьют плотные 70B.

⚔️ Dense 70B против MoE
Память считаем по всем параметрам (BF16), вычисления на токен — только по активным: остальные эксперты в этом токене не участвуют, их веса даже не читаются.
💾 Память под веса (BF16)
Llama 3.3 70B (dense)
140 ГБ
Qwen3.5 397B
794 ГБ
⚡ Параметров в работе на каждый токен
Llama 3.3 70B (dense)
70B
Qwen3.5 397B
17B
×4.1
Меньше вычислений на токен
×5.7
Больше памяти под веса

И вот где выстреливает факт из секции про роутер. Декод LLM упирается не в FLOPs, а в чтение весов из памяти (подробно разбирал в статье про KV-кэш). А раз невыбранные эксперты не читаются — на каждый токен из памяти тянутся веса только активных 17B. По скорости декода гигант ведёт себя как маленькая модель. Триллионный Kimi выдаёт токены бодрее плотной 70B: читать-то на каждом шаге приходится всего 32B.

⚠️⚠️ Подвох: на больших батчах халява тает

Это работает идеально при батче 1 (твой локальный чат). А вот на сервере с батчем 256 у каждого токена свой маршрут — суммарно за шаг активируются почти все эксперты, и читать из памяти приходится всё. Преимущество по FLOPs остаётся, по bandwidth — тает. Поэтому провайдеры лечат это expert parallelism и хитрым роутингом батчей — тот самый KV-aware/EP-роутинг, про который я писал в разборе NVIDIA Dynamo.


Цена вопроса: VRAM не обманешь

Халявы не бывает, и у MoE счёт выставляется в гигабайтах. Выбор экспертов происходит на каждом токене — заранее не угадать, кто понадобится, поэтому в памяти обязаны сидеть все. Qwen3.5 в BF16 — это ~794 ГБ весов при работе «как 17B». Загрузить только активных нельзя: через токен активными будут другие.

Что с этим делают:

  • Квантизация. Эксперты переживают агрессивную квантизацию лучше остальных частей модели — им можно 4 бита и ниже, держа attention и shared expert в точности повыше. Подробности механики — в статье про квантизацию.
  • Expert parallelism. Эксперты раскладываются по карточкам, токены летают между GPU. Так MoE гоняют в проде.
  • Выгрузка экспертов на CPU. Народный трюк для дома: attention и shared — на GPU, роутизируемые эксперты — в обычную RAM. На токен читается всего пара экспертов, и пропускной способности DDR5 на это почти хватает. Именно так люди крутят DeepSeek и Kimi на одной видеокарте с 512 ГБ RAM.

Как гонять MoE у себя

Шпаргалка. llama.cpp — тот самый трюк с выгрузкой экспертов одним флагом:

# все эксперты на CPU, attention + shared на GPU
llama-server -m kimi-k25-q4.gguf --n-gpu-layers 99 --n-cpu-moe 999

# или тоньше: часть слоёв экспертов оставить на GPU
llama-server -m model.gguf --n-gpu-layers 99 --n-cpu-moe 40
Почему трюк работает: на GPU остаётся всё плотное и горячее, эксперты уезжают в RAM — а на каждый токен из них читается только top-k, и пропускной способности DDR5 на пару экспертов хватает.

vLLM — expert parallelism на мультикарте:

vllm serve Qwen/Qwen3.5-397B-A17B-FP8 \
  --tensor-parallel-size 8 --enable-expert-parallel

SGLang — аналогично, --ep-size по числу карт. Остальные настройки — как для обычных моделей, гайд по движкам тут.

Что выбрать дома

Если модель влезает в VRAM целиком (квантованный Mixtral в 24 ГБ) — грузи как обычно, MoE сам по себе никакой настройки не требует. Не влезает — сначала квантизация, потом —n-cpu-moe, и только потом мысли о второй видеокарте.


TL;DR

1Что это: FFN (две трети весов) нарезан на N экспертов, роутер включает top-k на каждый токен в каждом слое
2Почему быстро: считаются и читаются из памяти только активные эксперты — триллионник декодит как 32B
3Почему умно: знания ∝ total, цена ∝ active; по качеству MoE ≈ плотная √(total × active)
4Боль обучения: без балансировки роутер коллапсирует — aux loss, z-loss или bias-трюк DeepSeek обязательны
5Цена: в VRAM живут все эксперты; лечится квантизацией, expert parallelism и выгрузкой экспертов на CPU

MoE — честная сделка: память в обмен на скорость и ёмкость. И да, «1T параметров» из громких анонсов на каждом токене шевелит скромные 32B — теперь ты знаешь, почему оно вообще ворочается. 🫡