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

Я взял MTPLX — сервер для Apple Silicon, который обещает двух‑трёхкратное ускорение генерации за счёт встроенных в модель голов multi‑token prediction (MTP). Посадил на него агента pi и прогнал одну и ту же сложную задачу в разных режимах. Ниже — что получилось, с цифрами, провалами и граблями.
Коротко:
MTP действительно ускоряет генерацию в 3 раза (21 → 63 ток/с на коротком промпте), но в реальной работе агента получается около 34 ток/с.
На сложной задаче время решения — 10–16 минут, и больше всего оно зависит от того, сколько модель решит думать, а не от настроек сервера.
Отключать или урезать размышления не выгодно: без них модель не довела код до рабочего состояния, на
lowвышло даже медленнее.SSD‑кеш и квантование KV‑кеша на этой задаче ничего заметного не дали.
Стенд
Железо |
MacBook Pro, M4 Max, 128 ГБ unified memory |
Сервер |
MTPLX 2.11.3 (приложение для macOS) |
Модель |
|
Контекст |
262 144 токена |
Профиль MTPLX |
|
Агент |
pi 0.87.1, чистая установка без расширений |
Как работает MTPLX
Обычная генерация — один проход модели на один токен. Спекулятивное декодирование сначала дёшево «угадывает» несколько следующих токенов, а потом одним проходом большой модели проверяет их все. Если угадано верно, за один проход получаем несколько токенов.
Обычно для угадывания нужна вторая, маленькая модель. У Qwen3.8 угадыватель встроен: это MTP‑головы, которые учились вместе с моделью. MTPLX использует их напрямую, так что лишней памяти под черновую модель не нужно. Проверка точная: распределение ответа не меняется, меняется только скорость.

У MTPLX есть встроенный подбор глубины черновика. Вот что он показал на моём Mac:
$ mtplx tune AR 21.1 tok/s 1.00x D1 48.3 tok/s 2.29x D2 61.7 tok/s 2.93x D3 63.1 tok/s 2.99x BEST

Тройное ускорение генерации — это реально. Вопрос в том, сколько от него остаётся в агентной работе.
Подключение к pi
MTPLX отдаёт OpenAI‑ и Anthropic‑совместимый API. В pi это обычный провайдер в ~/.pi/agent/models.json:
{ "providers": { "mtplx": { "name": "MTPLX (локально)", "baseUrl": "http://127.0.0.1:8000/v1", "api": "openai-completions", "apiKey": "none", "compat": { "supportsDeveloperRole": false, "supportsReasoningEffort": false }, "models": [{ "id": "mtplx-qwen38-27b-optimized-speed", "name": "Qwen3.8-27B MTPLX", "input": ["text", "image"], "reasoning": true, "contextWindow": 262144, "maxTokens": 32768, "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 } }] } } }
Если сервер требует ключ, pi умеет брать его командой, не сохраняя в конфиге: "apiKey": "!команда, которая печатает ключ".
Методика
Нужна была задача, которую нельзя решить «с наскока», но которая проверяется автоматически.
Задача: с нуля написать пакет minicalc — интерпретатор выражений по спецификации на страницу. Разбить на модули (лексер, парсер, вычислитель, ошибки) и учесть хитрые места:
приоритеты операций и правую ассоциативность , причём
-2 2 == -4, а2 ** -1 == 0.5;цепочки присваиваний
a = b = 4;встроенные функции с проверкой числа аргументов и константы, которые нельзя переприсвоить;
позиция символа для каждой ошибки, включая «неожиданный конец ввода»;
атомарность: упавшая инструкция не меняет состояние, а успешные до неё сохраняются;
запрет на
eval,execиast.
Проверка:
24 видимых теста лежат рядом с задачей, модель может их запускать.
30 скрытых тестов модель не видит. Они проверяют требования спецификации, которых нет в видимых тестах, — чтобы отличить «реализовал спецификацию» от «подогнал под тесты».
Все тесты сначала прогнаны на моей эталонной реализации: 54 из 54.
Запуск: pi -p --no-session --mode json с одним и тем же промптом, каждый раз в чистой папке. Из JSON‑лога pi считаются вызовы инструментов, ошибки и токены. Время — по часам. Скрытые тесты я запускаю после прогона.
Режимы размышлений. У Qwen3.8 три уровня — xhigh, medium, low — и они зашиты в шаблон чата модели. По умолчанию шаблон ставит xhigh. MTPLX для 27B‑модели подменяет умолчание на medium: так решили разработчики MTPLX по своему замеру времени на кодинговой задаче. Поэтому ниже xhigh — это родное поведение модели, а medium — умолчание MTPLX. Ещё есть off: размышления выключены совсем.
Правило обрыва. Если модель думает дольше, чем в эталонных прогонах, и не пишет код, прогон обрывается. Иначе один неудачный запуск съедал бы по часу.
Результаты
Режим размышлений |
Время |
Видимые |
Скрытые |
Вызовов / ошибок |
Выход, токенов |
До первого файла |
|---|---|---|---|---|---|---|
medium (умолчание MTPLX), прогон 1 |
10,0 мин |
24/24 |
30/30 |
18 / 2 |
17,8 тыс. |
6,2 мин |
medium, прогон 2 |
13,9 мин |
24/24 |
30/30 |
19 / 3 |
23,7 тыс. |
6,0 мин |
medium + SSD‑кеш |
16,2 мин |
24/24 |
30/30 |
22 / 4 |
23,3 тыс. |
— |
xhigh (умолчание модели) |
14,5 мин |
24/24 |
30/30 |
13 / 0 |
27,1 тыс. |
9,1 мин |
low |
18,3 мин |
24/24 |
30/30 |
30 / 4 |
30,2 тыс. |
7,7 мин |
off |
оборван на 8,5 мин |
0/24 |
— |
33 / 7 |
14,2 тыс. |
1,1 мин |

Ещё два прогона (xhigh + SSD‑кеш и medium + q8) я оборвал по правилу: на 13-й и 7-й минуте модель всё ещё думала и не написала ни строки.
Что видно из таблицы
Качество одинаковое во всех режимах с размышлениями. Все пять полных прогонов прошли 30 из 30 скрытых тестов. Модель сама писала проверочные скрипты на пограничные случаи из спецификации, поэтому и не провалилась на скрытых тестах.
Без размышлений модель не справилась. Режим
offначал писать код через минуту — в шесть раз раньше, чем medium. Дальше пошли пробы и ошибки: дважды целиком переписанные парсер и вычислитель, семь неудачных вызовов инструментов (в основном правки, где модель неверно помнила текущий текст файла), падения собственных проверок. На 8,5 минуте код даже не импортировался (SyntaxError). Модель экономит на обдумывании и потом переплачивает на отладке.lowне быстрееmedium. Я ждал, чтоlowдаст свои 5–7 минут. Вышло 18 минут, самый медленный прогон: 30 вызовов инструментов, 4 ошибки, и модель долго чинила требование, которого нет в спецификации (что(-8) ** 0.5должно выдавать ошибку).xhighдольше думает, зато работает чисто. 9 минут до первого файла, после этого ни одной ошибки инструментов, тесты прошли с первого запуска. По итоговому времени он в том же коридоре, что и medium.Разброс важнее режима. Три прогона medium дали 10, 14 и 16 минут. Разница между режимами меньше этого разброса, так что по одному прогону на режим ничего нельзя утверждать о скорости. Уверенно можно говорить только о крайних случаях:
offне работает,lowне экономит.
Куда уходит время
MTPLX отдаёт подробные метрики по каждому запросу (/metrics). Я сложил последние 22 запроса: прогон medium с SSD‑кешем и начало следующего.
Время |
Объём |
Скорость |
|
|---|---|---|---|
Генерация |
678 с (~70%) |
23,4 тыс. токенов |
34,5 ток/с |
Prefill новых токенов |
303 с (~30%) |
45,5 тыс. токенов |
~150 ток/с |
Взято из кеша в RAM |
~0 с |
340 тыс. токенов |
— |

Выводы:
В агентной работе генерация вдвое медленнее, чем в
tune: 34,5 ток/с вместо 63. Тюнинг меряет на коротких промптах, а у агента длинный контекст, где и проход модели дороже, и черновик угадывается хуже. MTP всё равно помогает, но не втрое.Основное время уходит на генерацию, а внутри неё — на размышления. В прогоне medium до первой строки кода проходит около 6 минут. При 34 ток/с это порядка 11–12 тысяч токенов размышлений. Скорость токенов стабильна, от запуска к запуску меняется лишь то, сколько модель решит подумать.
Prefill медленный, около 150 ток/с. Каждый прочитанный файл или вывод тестов стоит примерно 7 секунд на тысячу токенов. В этой задаче его сглаживает кеш в оперативной памяти: 340 тысяч токенов истории не пришлось обрабатывать заново. На большом репозитории prefill станет заметнее.
Что не помогло
SSD‑кеш сессий (
ssd_session_cache). 0 попаданий. Внутри сессии историю и так держит RAM‑кеш. SSD нужен, когда RAM‑кеш потерян: после перезапуска сервера или при возврате к старой сессии. Выключать не стоит, но и ускорения задачи от него ждать не надо.Квантование KV‑кеша q8. Prefill 185 ток/с, генерация 30,8 ток/с — в пределах шума относительно режима без квантования. Полный прогон с q8 не завершился: модель надумалась дольше обычного, и я его оборвал.
Подбор глубины черновика.
tuneподтвердил, что D3 уже оптимальна.
Для сравнения: oMLX
Ту же модель (обычный 4-битный MLX‑чекпоинт Qwen3.8–27B, без MTP) я запускал в oMLX с тем же окном контекста. По объёму размышлений за время прогона генерация шла примерно на 13 ток/с, за 25 минут модель так и не записала ни одного файла. Прогон оборвался посередине: на сервере запустили встроенный бенчмарк, и тот выгрузил модель. Так что это оценка, а не чистый замер. Отдельно сравню серверы в следующей статье.
Грабли
Запуск из образа DMG. Приложение MTPLX, запущенное прямо из смонтированного .dmg, создаёт среду выполнения со ссылками внутрь /Volumes/MTPLX …. Образ отмонтировался — сервер умер. Приложение нужно перетащить в «Программы».
«Ограниченный режим — MTPLX уже запущен». Я сменил порт в настройках, приложение перезапустило сервер, но старый процесс не отпустил порт. Новый сервер упал, приложение потеряло связь со старым и бесконечно «переподключало поток». Лечится полным выходом из приложения (Cmd+Q) и проверкой, что порт свободен.
Режим размышлений задаёт сервер, а не клиент. MTPLX по умолчанию игнорирует reasoning_effort из запроса анонимного клиента. Переключать режим надо на сервере — на лету, без перезапуска:
mtplx settings set --port 8000 reasoning=auto reasoning_effort=xhigh
А вот ssd_session_cache и paged_kv_quantization на лету не меняются: только через настройки приложения и перезапуск.
Вентиляторы на максимуме. MTPLX умеет сам управлять вентиляторами (режим smart и встроенная утилита thermalforge). Во время генерации он раскручивает их заранее, чтобы чип не сбрасывал частоты. Если шум мешает, режим вентиляторов можно отдать macOS, а профиль сменить с turbo на sustained. Попутно заметил, что после каждой сессии остаётся процесс thermal_sidecar: мелкая утечка, на работу не влияет.
Plan‑mode в агенте. У меня в pi было расширение, которое переводит любую задачу в режим «сначала план, потом подтверждение». В неинтерактивном pi -p подтверждать некому, и агент просто писал план и выходил. Для тестов такие расширения надо выключать.
Модель читает всё, что лежит в папке. В первых прогонах я складывал логи pi рядом с задачей, и модель тратила ходы, изучая собственный лог. Логи надо писать за пределы рабочей папки.
Ошибки в собственном тесте. Скрытый тест «в коде нет eval» искал подстроку eval( и помечал как нарушение обычный метод self._eval(...). Два прогона чуть не получили незаслуженный минус. Мораль: проверяйте тесты на эталонной реализации и внимательно смотрите на каждый провал, прежде чем списывать его на модель.
Выводы
MTPLX делает то, что обещает: генерация втрое быстрее без потери качества. В агентной работе на длинном контексте остаётся примерно 34 ток/с — всё равно ощутимо больше, чем без MTP.
Сложная задача занимает 10–16 минут, и узкое место — не сервер, а объём размышлений модели. Настройки сервера на это почти не влияют.
Размышления не урезайте. Родной xhigh и medium, который подставляет MTPLX, дали одинаковую точность и время в пределах разброса. xhigh работает чище, с меньшим числом ошибок по ходу. low и off время не экономят.
Меряйте несколько прогонов. Разброс одного режима (10–16 минут) больше разницы между режимами.
Кеши и квантование оставьте на случай, где они нужны: SSD‑кеш — для долгих сессий и перезапусков, q8 — если упираетесь в память на огромном контексте.
В следующей части сравню с другим сервером на тех же задачах, а заодно проверю, как всё это ведёт себя на реальном репозитории, где prefill становится главной проблемой.
Комментарии (8)

hardtop
24.09.2026 05:44Полезный тест, спасибо! Отдельно хотел спросить про шум вентиляторов - насколько громко? И можно ли как-то снизить нагрузку на ноут для снижения шума, пусть и пожертвовав скоростью генерации?

VladimirVP Автор
24.09.2026 05:44Спасибо! Замерил специально под ваш вопрос: пять минут непрерывной генерации на Qwen3.8-27B, обороты и температура каждую секунду. Децибелы не мерил, так что ориентир — обороты вентиляторов. У этого MacBook Pro (M4 Max) в простое около 2 300–2 500 об/мин, максимум примерно 7 800.
turbo + fan smart (по умолчанию): 35 ток/с, вентиляторы ~7 850 об/мин — максимум, с первой секунды, пик 107 °C.
turbo + fan default (вентиляторы у macOS): 25 ток/с, ~5 350 об/мин, разгон за ~30 с, пик 116 °C.
sustained + fan default: 20 ток/с, ~5 350 об/мин, пик 115 °C.
Насколько громко. С настройками по умолчанию — на полную: MTPLX сам выкручивает вентиляторы на максимум сразу, не дожидаясь нагрева, чтобы чип не сбрасывал частоту. Звук как у ноутбука под рендером.
Можно ли тише. Да, одним переключателем: в настройках MTPLX сменить режим вентиляторов со smart на default, чтобы ими управляла macOS. Обороты падают примерно на треть, но чип сильнее греется и сбрасывает частоту, и генерация проседает на те же ~30%. Щадящий профиль sustained сверх этого шум не снижает: macOS разгоняет вентиляторы до того же уровня, а скорость падает ещё на пятую часть. Так что его не советую. Из непроверенного остаётся Low Power Mode в macOS: он сильнее всего ограничивает чип.

OlegZhigulin
24.09.2026 05:44А еще бы прикладывать сколько памяти он отьедает, понятно что когда 128 можно не думать
А когда 24 уже начинаешь выбирать
СКолько контекст занимал?

VladimirVP Автор
24.09.2026 05:44MTPLX сообщает о своём плане памяти при старте:
Контекст. В этой задаче агент набирал 26–40 тыс. токенов за запрос: системный промпт pi, описания инструментов, спецификация, код и вывод тестов. Окно стояло на 262 тыс., реально использовалось меньше 15%.
Веса — 20,7 ГБ. Это 4 бита плюс MTP-головы, благодаря которым и идёт ускорение.
Контекст дешёвый. У модели гибридное внимание, полный KV-кеш только у 16 слоёв из 64, поэтому один токен стоит 64 КБ. 40 тыс. токенов ≈ 2,6 ГБ, 100 тыс. ≈ 6,5 ГБ, все 262 тыс. ≈ 16 ГБ.
Служебные буферы — около 3 ГБ.
Итого на этой задаче примерно 26 ГБ.
Нюанс: кеш сессий. На 128 ГБ MTPLX разрешал себе держать в памяти до 48 ГБ кеша уже обработанных промптов, чтобы не пересчитывать историю. На машине с меньшей памятью этот лимит, видимо, ниже, но это я не проверял.
Про 24 ГБ. macOS отдаёт GPU примерно две трети–три четверти памяти, то есть около 16–18 ГБ. Сборка 27B для MTPLX (20,7 ГБ только веса) туда не влезает. В линейке MTPLX для такого объёма есть Qwen3.5-9B с MTP, по их данным ей нужно от 16 ГБ. Её я не тестировал.
Politura
На 128 Гб памяти стоит попробовать Qwen3.8-Flash-Next, должно быть сильно быстрее и при этом умнее.
Какой-то измененный чат темплейт? У Qwen3.8 27B по умолчанию xhigh, а не медиум.
VladimirVP Автор
Спасибо. Интересно потестирую.
VladimirVP Автор
Спасибо, точное замечание. Шаблон не менялся, он штатный: в нём прямо прописано reasoning_effort|default(‘xhigh’). Medium подставляет сам MTPLX. В его коде для Qwen3.8-27B стоит default_effort=“medium”, и в комментарии авторы объясняют, что выбрали его по замеру времени на кодинговой задаче. Для Flash-Next MTPLX, наоборот, оставляет родной xhigh. Так что в моих замерах «medium» — это умолчание MTPLX, а родному поведению модели соответствует прогон xhigh: 14,5 минуты, 30 из 30 скрытых тестов. Вывод от этого не меняется: xhigh и medium одинаково точны, а разница во времени меньше разброса между запусками. xhigh даже работает чище, без ошибок по ходу. Поправил это в тексте, чтобы не путать.