Что такое SSD-стриминг MoE-моделей и почему это меняет правила для локального инференса
Проект Inferred Thoughts собрал движок инференса, который запускает Qwen3.8-Flash-Next 177B (176,9B параметров, NVFP4 GGUF, 119 ГиБ) на одной RTX 5060 Ti с 16 ГБ VRAM, Ryzen 7 9700X, 32 ГБ DDR5 и Gen5 NVMe SSD на 1 ТБ. Большая часть весов остается на накопителе и читается по мере того, как роутер выбирает экспертов на очередном токене. Заявленные результаты: 9,06 tok/s декодирования на бенчмарк-турне и 10,4 tok/s на лучшем турне, при этом llama.cpp на той же машине выдает в среднем 4,9 tok/s. Описание движка и замеры опубликованы автором проекта.
Механика опирается на особенность MoE-архитектуры: модель не использует все параметры сразу. Qwen3.8-Flash-Next берет по 10 экспертов в каждом из 48 слоев, то есть 480 экспертов на токен из общего пула, а остальные веса в этом токене не участвуют. Движок держит в быстрой памяти горячий набор, а редкие эксперты подтягивает с NVMe по требованию. Узким местом становится диск, зато требования к объему RAM падают радикально: 32 ГБ хватает для модели на 119 ГиБ.
Чем SSD-стриминг отличается от оффлоада в RAM и VRAM
При классическом оффлоаде часть слоев или экспертов выгружается в системную RAM и подкачивается в VRAM по ходу прохода по слоям. Модель обязана уместиться в сумму VRAM и оперативной памяти: если веса не влезли в 16 ГБ видеопамяти и 32 ГБ DDR5, вариант не запускается, приходится брать более агрессивный квант или добавлять память.
SSD-стриминг снимает это требование. Из 119 ГиБ в VRAM и pinned RAM помещается около 20 ГиБ, а 99 ГиБ остаются на SSD: 48,5 ГиБ routed-экспертов, которые стримятся по мере выбора роутером, и 50,7 ГиБ хеш-таблицы n-gram. 32 ГБ DDR5 достаточно не потому, что модель в них влезла, а потому, что ей не нужно влезать. Платите вы пропускной способностью накопителя и задержкой чтения.
Похожую логику уже проверяли в других проектах: дисковый тир Overspill для движка FreeToken позволял запустить DeepSeek-V4-Flash REAP-150B примерно на 85 ГБ на RTX 3060 12 ГБ. Разница в том, какие компоненты модели вынесены на диск и насколько агрессивно движок предугадывает обращения к экспертам.
Отдельно про хеш-таблицу n-gram на 50,7 ГиБ: она читается с SSD по 16 строк на токен, а автор описывает ее как задел под qwen4 ngram. Компонент экспериментальный, и ожидать от него отдачи, пропорциональной размеру, оснований нет.
Конфигурация и раскладка памяти: как 177B-модель умещается в 16 ГБ VRAM и 32 ГБ RAM
Тестовая машина: RTX 5060 Ti 16 ГБ, Ryzen 7 9700X, 32 ГБ DDR5, Gen5 NVMe SSD на 1 ТБ, Windows 11. Модель: Qwen3.8-Flash-Next, 176,9B параметров, формат NVFP4 GGUF, размер 119 ГиБ. Опубликованная раскладка по уровням памяти выглядит так (по данным проекта Inferred Thoughts):
| Компонент | Где лежит | Объем |
|---|---|---|
| Dense-веса | VRAM | 4,4 ГиБ |
| Горячие routed-эксперты | VRAM | 8,8 ГиБ |
| Таблица эмбеддингов | RAM | 0,6 ГиБ |
| Следующие по горячности эксперты | pinned RAM | 6,0 ГиБ |
| Остальные routed-эксперты | SSD | 48,5 ГиБ |
| Хеш-таблица n-gram | SSD | 50,7 ГиБ |
| Итого | VRAM, RAM и SSD | 119 ГиБ |
В VRAM и pinned RAM суммарно оказывается около 20 ГиБ, на SSD остается 99 ГиБ. Pinned RAM здесь решает конкретную задачу: страницы памяти зафиксированы и не могут уехать в файл подкачки, поэтому следующая по горячности группа экспертов на 6,0 ГиБ доступна для копирования в VRAM без риска упереться в своп. На машине с 32 ГБ это важно, иначе часть весов ушла бы на диск и скорость просела.
Почему NVFP4 GGUF, а не Q4_K_M или другой формат
NVFP4 - 4-битный формат с плавающей точкой, рассчитанный на тензорные ядра Blackwell (sm_120). Движок выполняет матмулы NVFP4 как FP4 x FP4 прямо на тензорных ядрах, без предварительной распаковки. Распаковка отнимала бы время и память на каждом умножении, поэтому нативная поддержка FP4 снижает накладные расходы на вычисления.
Обратная сторона: формат привязан к RTX 50-серии, и на RTX 40-серии этот сценарий в v1 не заработает даже при достаточном объеме VRAM. Заявлений о превосходстве NVFP4 над Q4_K_M или Q8 по качеству в описании проекта нет: речь идет о скорости и поддержке FP4-матмулов, а не о сравнении качества квантов.
Роль Gen5 NVMe и 8 потоков чтения
На каждый токен с SSD читается около 270 МиБ, чтение идет на 8 потоках. Пропускная способность накопителя прямо влияет на tok/s: чем быстрее NVMe отдает данные, тем меньше движок простаивает. В тестовой конфигурации использовался Gen5 NVMe на 1 ТБ; данных о поведении на Gen4 в описании нет, поэтому обещать сопоставимую скорость на более медленном диске нельзя.
По записи накопитель почти не нагружен: движок только читает, так что износ от записи минимален. Зато при длительных прогонах SSD нагревался до 70 °C. Для многочасовых сессий это аргумент в пользу радиатора на накопителе и нормального продува корпуса.
Как работает движок Inferred Thoughts: GCLOCK, lookahead-префетч и FP4-матмулы
Основную часть прироста дают четыре механизма.
- GCLOCK-вытеснение. VRAM хранит dense-веса и самые горячие эксперты. Когда места не хватает, вытесняются блоки с наименьшей вероятностью использования, поэтому кэш подстраивается под реальные паттерны роутера, а не под формальный порядок слоев.
- Lookahead-префетч. Движок предугадывает, какие эксперты понадобятся на следующем слое, и запускает их чтение заранее. Задержка SSD частично перекрывается вычислениями текущего слоя.
- 8 потоков чтения с NVMe. Запросы к накопителю идут параллельно, что позволяет выжать из Gen5 близкую к предельной полосу на блоках нужного размера.
- Матмулы FP4 x FP4. Умножения выполняются на тензорных ядрах в исходном 4-битном формате, без распаковки весов в FP8 или FP16.
Как эти механизмы складываются в цифры: каждый токен использует 480 экспертов (10 в каждом из 48 слоев), около 377 из них уже лежат в VRAM или RAM, а примерно 103 читаются с SSD, что и дает около 270 МиБ чтения на токен. Около 75% обращений к экспертам попадают в память.
Почему 75% попаданий в память - это ключевая метрика
Если бы все 480 экспертов приходили с SSD, объем чтения на токен вырос бы в разы, и диск стал бы единственным поставщиком данных для вычислений. 75% попаданий означают, что с накопителя приходит примерно 103 обращения из 480, то есть около четверти. Если разделить 270 МиБ на 103 чтения, получается порядка 2,6 МиБ на эксперта; это арифметическая прикидка из опубликованных цифр, а не отдельный замер.
GCLOCK работает именно на эту метрику: чем точнее кэш удерживает горячие эксперты, тем выше доля попаданий и тем меньше данных тянется с диска. Lookahead-префетч подстраховывает оставшуюся четверть: чтение стартует до того, как оно понадобится, и задержка SSD частично скрывается за вычислениями.
Скорость в цифрах: 9-10 tok/s против 4,9 tok/s у llama.cpp
Сравнение корректно, потому что обе цифры получены на одной машине: RTX 5060 Ti 16 ГБ, Ryzen 7 9700X, 32 ГБ DDR5, Gen5 NVMe, Windows 11. Замеры проекта дают 9,06 tok/s на бенчмарк-турне и 10,4 tok/s на лучшем турне, llama.cpp на той же конфигурации - в среднем 4,9 tok/s декодирования. Prefill у движка составил 49,2 tok/s на промпте из 5,5k токенов (сводка замеров).
Разница объясняется архитектурой, а не тем, что llama.cpp плох. llama.cpp не рассчитан на стриминг экспертов с SSD и на нативные FP4-матмулы Blackwell, поэтому на этой конфигурации упирается в собственную логику размещения весов. Разбор настроек llama.cpp на примере Qwen 3.6 27B на RTX 5090 показывает обратную ситуацию: когда модель помещается в память, тот же движок выдает куда более высокие цифры.
9-10 tok/s - скорость, при которой вывод читается в темпе появления текста. Для длинных ответов и агентных сценариев с десятками вызовов этого мало: 500 токенов ответа займут около 50 секунд, а каждый новый шаг агента добавляет еще один prefill.
Что означает prefill 49,2 tok/s на практике
Prefill - обработка входного промпта, decode - генерация ответа. 49,2 tok/s на промпте из 5,5k токенов означают примерно 112 секунд (5500 / 49,2) до первого токена ответа. На коротких репликах пауза незаметна, при работе с длинным контекстом или большим файлом в промпте она ощутима. Данных по prefill на других длинах промпта в описании проекта нет, экстраполировать эти 49,2 tok/s на 20k или 128k токенов не стоит. Методику честного разделения prefill и decode мы разбирали на примере nInfer, vLLM и llama.cpp.
Ограничения v1: только RTX 50-серии, Windows 11/WSL2 и greedy-декодирование
Список ограничений короткий, но жесткий:
- GPU только RTX 50-серии (Blackwell, sm_120). Причина в FP4-матмулах: они завязаны на тензорные ядра Blackwell.
- ОС только Windows 11 и WSL2. Другие платформы в v1 не тестировались.
- Декодирование только greedy. Параметров temperature и top-p нет, поэтому ответы детерминированнее, а их разнообразие ограничено. Для извлечения данных и повторяемых задач это плюс, для творческого чата заметный минус.
OpenAI-совместимый сервер в сборке уже есть: он рендерит собственный chat template модели, поддерживает tool calls, отделяет reasoning от ответа и имеет встроенную чат-страницу. Но tool calls автор называет багованными и тестировал только с Cline. Считать этот сценарий готовым к рабочему использованию нельзя.
Кому v1 уже подходит, а кому стоит подождать
Если у вас RTX 50-серии, Windows 11 или WSL2 и задача не требует sampling, движок можно пробовать: он дает примерно вдвое больше tok/s, чем llama.cpp, на модели, которая иначе на такой машине просто не запустится. Если у вас RTX 40-серии, Linux или нужны temperature и top-p, v1 не подойдет: разумнее смотреть на другие решения или ждать v2. Для 12 ГБ VRAM есть отдельные обходные пути: запуск Qwen3.8-Flash-Next в квантовании IQ3_XXS на RTX 5070 с 12 ГБ дает 14-15 токенов/с, но с другими компромиссами по качеству кванта и длине контекста.
Помимо 177B: Qwen3.6-35B-A3B NVFP4 и другие сценарии
Кроме 177B-модели движок поддерживает Qwen3.6-35B-A3B NVFP4. Она умещается в VRAM и RAM целиком, и на той же машине с настроенной конфигурацией выдает 47,3 tok/s декодирования при контексте около 4k и 591 tok/s prefill.
Для такой модели SSD-стриминг не нужен: веса уже в памяти, накопитель в работе не участвует. Высокие цифры здесь дают нативные FP4-матмулы и эффективный кэш, а не чтение с диска. Практический смысл примера в том, что один движок закрывает оба сценария: модель не влезает в память и модель влезает, но хочется быстрее. 47,3 tok/s - замеры проекта на конкретной конфигурации, а не универсальный ориентир для этой модели.
Qwen3.6-35B-A3B автор называет этапом, на котором движок обкатывали перед 177B. Если у вас 16 ГБ VRAM и 32 ГБ RAM, начинать логичнее с 35B: она быстрее покажет, как ведут себя кэш и накопитель, и не потребует держать на диске 119 ГиБ данных.
Что проверить перед запуском и чего ждать от v2
Чек-лист для первого запуска:
- GPU RTX 50-серии (Blackwell, sm_120). На других архитектурах v1 не работает.
- Windows 11 или WSL2.
- Gen5 NVMe; в тестовой конфигурации накопитель на 1 ТБ. Быстрый SSD критичен, потому что через него идут примерно 270 МиБ на каждый токен.
- 32 ГБ DDR5. Часть памяти работает как pinned RAM под следующий уровень экспертов, поэтому свободной оперативки должно быть много.
- Модель в формате NVFP4 GGUF; для 177B это 119 ГиБ на диске.
Три вещи, которые стоит держать в голове. Декодирование только greedy, sampling недоступен. Tool calls пока багованные и проверялись только с Cline. При длительных прогонах SSD нагревается до 70 °C, при этом на запись движок почти не работает, так что износ от записи минимален.
По v2 автор ожидает около 14-15 tok/s декодирования за счет улучшенного SSD-стриминга. Это прогноз проекта, а не измеренный результат: подтвержденных замеров v2 в описании нет.
Оценивать подход стоит по инженерной части. SSD-стриминг MoE работает за счет кэша горячих экспертов, префетча следующего слоя, восьми потоков чтения NVMe и нативных FP4-матмулов. На RTX 5060 Ti 16 ГБ и 32 ГБ DDR5 эта связка дает вдвое больше tok/s, чем llama.cpp на той же машине, но платить приходится совместимостью только с RTX 50-серии и Windows 11 или WSL2, отсутствием sampling и паузой на prefill. Если ваш сценарий попадает в эти рамки, начните с Qwen3.6-35B-A3B, замерьте реальную скорость своего накопителя и только после этого качайте 119 ГиБ под 177B.