EnglishРусский Map

deltafin

title
deltafin
type
toolbox
summary
Запуск весов Kimi K3 на 2.8T параметров на одном Mac с Apple Silicon со стримингом MXFP4-экспертов по HTTP на диск
tags
python, llm, local-models, moe, inference, apple-silicon, watchlist
language
Python, C (NEON / SSSE3), Metal
license
MIT
created
2026-07-29
updated
2026-07-29
lang
ru
translation_of
deltafin
source_updated
2026-07-29
translated
2026-09-01
translator
lllm/antigravity/gemini-3.7-flash-high

Deltafin запускает kimi-k3 - 2.8T параметров, около 1.56 ТБ весов в MXFP4 - на одном Mac с Apple Silicon. Это работает благодаря тому, что модель с архитектурой mixture-of-experts на каждый токен задействует лишь небольшую часть весов, поэтому остальному объёму незачем находиться в RAM. На M1 Max мейнтейнера скорость составляет один токен за 14.6 секунды, о чём README говорит с подкупающей прямотой: "исследовательский артефакт, а не практичный сетап для чата".

Как разделена модель

Три части, и каждая обрабатывается по-своему.

Резидентный остов (spine) - attention, общие эксперты, латентные проекции, эмбеддинги - занимает около 114 ГБ в bf16 или 53-60 ГБ при квантовании в int8. Он скачивается один раз, считывается слой за слоем из локального хранилища на каждом токене, а затем вычисляется на MPS, CUDA или CPU.

82 432 маршрутизируемых эксперта занимают около 1.45 ТБ. Роутер K3 выбирает по 16 экспертов на слой на протяжении 92 слоёв, так что на токен считывается 25.8 ГБ данных экспертов и ничего лишнего. Их можно установить локально целиком, если хватает места на диске, либо позволить Deltafin скачивать каждого недостающего эксперта с Hugging Face отдельным HTTP-запросом диапазона (range request) в растущий дисковый кэш.

Прямой проход (forward pass) - это оригинальный код моделирования Moonshot без изменений, где чистый PyTorch-shim заменяет ожидаемые им CUDA-ядра из fla. Этот shim заново реализует рекуррентность kimi-delta-attention, короткую свёртку и gated norm; поблочное (chunked) и пошаговое выполнение сходятся с точностью около 1e-9. При генерации (decode) рекуррентность считается на CPU, так как компактное состояние KDA проще держать там, чем гонять череду вызовов ядра на GPU.

Заметки о реализации в Deltafin - это самое ясное публичное описание структуры K3: 93 слоя декодера, 69 KDA и 24 MLA, 896 экспертов на слой, маршрутизация top-16, 96 шардов safetensors.

Два режима установки

./venv/bin/python tools/setup_k3.py --full     # ~1.7 TB, 5-10 hours, resumable
./venv/bin/python tools/setup_k3.py --stream   # ~215 GB, ~30 minutes

Выбор определяет одно число. С локального диска 25.8 ГБ данных экспертов на токен считываются примерно за 4 секунды, а по сети на это уходят минуты. Поэтому полная установка генерирует токен за 14.6 с, а стриминговая - примерно от 3 минут на токен для всего, чего ещё нет в кэше. Стриминг позволяет опробовать модель, не выделяя сразу 1.7 ТБ; tools/fetch_experts_all.py докачивает остальное позже, поддерживая докачку и запросы диапазонов, без переустановки. Сервер и CLI выводят предупреждение при запуске, если модель всё ещё в режиме стриминга.

Использовать можно через CLI или OpenAI-совместимый сервер:

./venv/bin/python tools/kimi_run.py --chat --prompt "What are the three largest moons of Saturn?"
./venv/bin/python tools/serve_openai.py --port 8000

Эндпоинты /v1/chat/completions, /v1/completions, /v1/models и потоковая отдача работают, так что на него можно натравить любой инструмент, читающий OPENAI_BASE_URL - ровно такую подмену cc-mirror автоматизирует для вариантов Claude Code. Самое интересное здесь - ограничения: таймауты на клиенте нужно ставить на несколько часов, декодирование только жадное (параметры temperature и top_p принимаются, но игнорируются), запросы строго по одному (на второй возвращается 429), а агентное написание кода остаётся "любопытным экспериментом, а не рабочим процессом", поскольку из-за длинных системных промптов prefill обходится слишком дорого.

На что уходит время

Эталонная машина автора проекта - M1 Max первого поколения (10 ядер CPU, 32 ядра GPU, 64 ГБ RAM, встроенный NVMe), где вся модель сохранена локально, остов и выходной слой квантованы в int8, MoE работает на Metal, декодирование жадное, а трейсинг выключен. Результаты шести запусков полной модели в сбалансированных сериях ABBA/BAAB (приведены медианы):

Метрика Первая рабочая версия Текущая
Prefill / первый токен (промпт из 5 токенов) 2 429 с 28.0 с (24.9-37.9)
Установившийся decode, локальные эксперты ~20 мин/токен 14.6 с/токен (0.0503-0.0779 ток/с)
Decode со стримингом экспертов ~20 мин/токен ~3 мин/токен, упирается в сеть

Это примерно 4.1 токена в минуту. Бюджет времени на токен раскладывается так: ~5 с на ожидание чтения резидентного остова, ~4.3 с на чтение 16 выбранных экспертов на слой, ~3 с на применение остова, ~2 с на attention и нормализации по 93 слоям, ~1 с на матричные умножения MoE. Генерация упирается в пропускную способность диска при чтении остова: повторное считывание 53 ГБ на каждый токен на скорости около 7 ГБ/с, которую обеспечивает такой паттерн доступа, занимает порядка 7.5 с из медианных 14.6 с. Единственные лекарства - больше RAM или более компактный остов.

Техники, давшие ускорение в 82 раза

Каждое решение перед включением в код измерялось на реальных весах. Большинство из них - это адаптации, а не новые изобретения: README прямо ссылается на colibri, ds4 от antirez и llama.cpp/ggml.

Загрузка экспертов объединена (coalesced): все шесть тензоров каждого эксперта оказались непрерывными внутри файлов шардов (проверили все 82 432), поэтому один эксперт скачивается единым range-запросом на 17.55 МБ по keep-alive соединению, что примерно в 6.4 раза быстрее поштучного скачивания тензоров. Дисковый кэш хранит байты шардов как есть - без контейнеров и парсинга. 16 экспертов слоя считываются пулом потоков вместе через pread вместо постраничной подгрузки по требованию (page fault); в macOS флаг F_NOCACHE защищает системный page cache, нужный для остова, от вымывания 25 ГБ трафика экспертов на токен. При холодном чтении это дало 6.85 ГБ/с через pread против 0.87 ГБ/с на page fault'ах, сократив время с 40 с до 4.3 с на токен.

В части вычислений fused-ядро деквантования MXFP4 + GEMV (tools/fused_gemv.c) выполняет деквантование и умножение за один проход через табличный поиск на 16 элементов, применяя масштаб e8m0 целочисленной арифметикой к экспоненте fp32. Реализовано на NEON для aarch64 и SSSE3/FMA для x86-64, с побитовым совпадением с эталоном. Собственное Metal-ядро деквантования заменило умножение с широковещанием по строкам (row-broadcast), которое MPS выполнял на скорости 43 ГБ/с (при 334 ГБ/с для простого копирования тех же байтов), на объединённую операцию int8 -> fp32 + scale + copy со скоростью 297 ГБ/с. Это снизило время загрузки слоя со 118 мс до 21 мс при max|diff| = 0. Поскольку у всех 69 слоёв KDA одинаковый набор форм тензоров, а у всех 24 слоёв MLA - другой, два постоянных слоя-шаблона в памяти устройства принимают веса каждого слоя через copy_(), исключая лишние аллокации.

Квантование здесь - скорее решение для I/O, чем для вычислений (общую картину см. в llm-quantization). Остов в int8 вдвое снижает объём дискового ввода-вывода резидентной части на токен. В тестах порядок первых пяти кандидатов на следующий токен полностью сохранился, а верхний логит сдвинулся всего на 0.07%. Упакованный выходной слой в int8 для MPS дал +17.3% к скорости steady decode, +23.1% к prefill, +26.8% к общей пропускной способности и уменьшил объём памяти выходного слоя с 4.7 ГБ до 1.17 ГБ. Упакованный путь int8 для Q/K/V в KDA пока остаётся опциональным (K3_INT8_KDA_QKV=1), так как первый A/B-тест показал +2.8% на decode и −4.7% на prefill при перекрывающихся интервалах замеров.

N-граммная спекуляция включена по умолчанию и работает без потерь качества: черновые варианты бесплатно извлекаются сопоставлением суффиксов в уже сгенерированном тексте и проверяются пакетом на две позиции. При отклонении черновика состояние восстанавливается бит в бит за счёт сохранения старых иммутабельных объектов состояния, без клонирования ~475 МБ. Приём окупается по необычной причине: для прогретого токена доминируют резидентный ввод-вывод и вычисления, а не загрузка экспертов, поэтому вторая позиция достаётся практически даром.

Платформы и их асимметрия

macOS на Apple Silicon использует MPS плюс Metal-ядро для MoE с нативным запасным вариантом (fallback) на CPU. Поддержка Linux с картами NVIDIA намеренно названа гибридной: CUDA ускоряет резидентный остов и attention, но маршрутизируемые эксперты в MXFP4 всё ещё выполняются нативным ядром на CPU, так как ядра MoE для MXFP4 под CUDA пока нет. Под Linux x86-64 требуется уровень инструкций x86-64-v3 (AVX2, FMA3) и задействуется ядро SSSE3/FMA; на aarch64 используется NEON. Скрипт build_native.py выбирает .dylib или .so, выставляет флаги ISA хоста и проверяет символы и ABI перед установкой.

Запуск участника сообщества на NVIDIA DGX Spark (GB10 Grace-Blackwell, 128 ГБ объединённой памяти LPDDR5X) дал самую показательную цифру в README. Из четырёх конфигураций вариант int8 + CUDA отработал за 221 с против 865 с у bf16 + CPU - сквозное ускорение составило почти 4x вместо двукратного, которого можно было бы ожидать от двукратного сокращения размера остова. Остов на 107 ГБ в bf16 не оставлял места для системного кэша страниц под экспертов, тогда как int8-остов размером ~53 ГБ освободил достаточный запас памяти, благодаря чему ожидание предзагрузки сократилось с 676 с до 18 с. Квантование изменило режим работы I/O, а не только вычисления. Тот же рычаг задействует moe-cpu-offload в llama.cpp, уровнем хранения ниже.

Ограничения

Автор говорит о них прямо. Медианное время в 14.6 секунды на токен далеко от интерактивного режима; длинные промпты обходятся дорого, так как prefill затрагивает множество экспертов; тестового стенда качества пока нет, поэтому компромиссы между скоростью и точностью при квантовании с потерями пока обосновываются теоретически, а не измеряются (в планах стоит замер средней NLL относительно официального API, идея взята из ds4). Все основные цифры получены на одном M1 Max, а данные по DGX Spark взяты из единичного прогона от сообщества в pull request #2 и автором не воспроизводились. Первым пунктом в роадмапе стоит нативное ядро CUDA для MoE в MXFP4.

Выдача строго жадная и воспроизводимая - один и тот же промпт даёт одни и те же токены от запуска к запуску, что и делает приведённые выше A/B-замеры осмысленными.

Проект отслеживается в watchlist: к нему стоит вернуться, когда появятся CUDA-ядро для MXFP4 и замеры качества через NLL - именно от них зависит, останется ли это доказательством принципиальной возможности или превратится в применимый способ запуска K3 вне дата-центров. Пока же это противовес тезису из local-ai-is-not-opus: запустить передовую открытую модель дома можно, просто цена измеряется в секундах на токен.

Собственный код Deltafin распространяется под лицензией MIT; tools/fla/ - это порт семантики из flash-linear-attention (MIT), а веса K3 и код моделирования остаются под лицензией Moonshot и загружаются при установке, а не поставляются в составе репозитория. Проект не связан с Moonshot AI.