Вторая часть. Первая — «Локальный агент для кода на Mac: MTPLX + pi + Qwen3.8-27B».

В первой части я посадил кодового агента pi на локальную Qwen3.8-27B через MTPLX и прогнал сложную задачу в разных режимах размышлений. Осталось сомнение, которое MTPLX сам не снимает: сколько тут даёт его многотокенное предсказание (multi-token prediction, MTP), а сколько сработало бы на любой MLX-обвязке?

Толчком стал разговор с ChatGPT. Я спросил, какой MLX-сервер поставить на MacBook Pro с M4 Max, и получил уверенный ответ: oMLX быстрее и качественнее остальных на таком железе. Звучало правдоподобно, проверить было интересно вдвойне. Я поставил oMLX, взял ту же модель и ту же задачу и повторил все те же режимы. Заодно отвечаю на вопросы из комментариев к первой части — про режим по умолчанию, шум вентиляторов и память.

Итог короткий: совет не подтвердился. В моих прогонах MTPLX заканчивал задачу в 2,8–6,4 раза быстрее, а по скрытым тестам связки сравнялись. Оговорки тоже короткие: сборки модели разные, а каждый режим на oMLX я запускал по одному разу.

Стенд

MTPLX

oMLX

Версия

2.11.3

0.7.0.dev4

Модель

Youssofal/Qwen3.8-27B-MTPLX-Optimized-Speed

mlx-community/Qwen3.8-27B-4bit

Квантование

4 бита

4 бита

Размер весов

20,7 ГБ (с MTP-головами)

16,1 ГБ

MTP

да, глубина черновика D3

нет: в чекпоинте нет весов MTP-голов

Окно контекста

262 144

262 144 (по умолчанию было 32 768 — пришлось поднять)

Железо и агент те же, что в первой части: MacBook Pro на M4 Max со 128 ГБ, pi 0.87.1 без расширений. Задача тоже та же: с нуля написать интерпретатор выражений minicalc по спецификации, 24 видимых теста, которые модель может запускать, и 30 скрытых, которых она не видит.

Важная оговорка про сравнение: сервер другой, но и чекпоинт формально другой. MTPLX-сборка — это та же Qwen3.8-27B в 4 битах, к которой добавлены MTP-головы и веса перепакованы под собственный рантайм. Без MTP-голов MTPLX просто не работает, а oMLX их из этой модели не использует. Так что сравнивается связка «сервер + сборка под него», как это и выглядит для пользователя.

Поправка к первой части: какой режим «по умолчанию»

В комментариях к первой части правильно заметили: у Qwen3.8-27B по умолчанию xhigh, а не medium. Это прописано прямо в шаблоне чата модели: reasoning_effort|default('xhigh'). medium подставляет сам MTPLX — в его коде для этой модели стоит default_effort="medium", выбранный разработчиками MTPLX по их собственному замеру на кодинговой задаче.

oMLX ничего не подставляет: он передаёт уровень размышлений в шаблон только тогда, когда его прислал клиент. pi его не шлёт, поэтому «из коробки» на oMLX модель работает на родном xhigh. Чтобы прогнать другие режимы, я задавал их на стороне сервера, в настройках модели ~/.omlx/model_settings.json:

"Qwen3.8-27B-4bit": {
  "chat_template_kwargs": { "reasoning_effort": "medium" }
}

А для режима без размышлений — "enable_thinking": false.

Результаты

Режим

MTPLX

oMLX

oMLX медленнее в

medium (умолчание MTPLX)

10,0 / 13,9 / 16,2 мин

37,5 мин

~2,8×

xhigh (умолчание модели)

14,5 мин

92,8 мин

6,4×

low

18,3 мин

72,0 мин

3,9×

off

оборван на 8,5 мин: код не импортируется

оборван на 68 мин: код зависает

—

Во всех завершённых прогонах с размышлениями обе связки прошли скрытые тесты: 30 из 30.

Время решения задачи на MTPLX и oMLX: разница от 2,8 до 6,4 раза
Время решения задачи на MTPLX и oMLX: разница от 2,8 до 6,4 раза

Коэффициенты в таблице посчитаны против среднего времени MTPLX. Для medium это среднее из трёх прогонов, 13,4 минуты. Выбор базы заметно меняет цифру: если поделить 37,5 на самый быстрый прогон в 10 минут, выйдет 3,75, а на самый долгий в 16,2 — 2,3. И есть ещё одна оговорка: запуск на 16,2 минуты был с SSD-кешем, как я писал в первой части, так что это среднее по приведённым попыткам, а не по повторениям с полностью одинаковыми настройками. Для xhigh и low у MTPLX по одному прогону, поэтому там сравниваются отдельные времена без усреднения.

Вот что происходило на oMLX:

Режим

Время

Вызовов инструментов / ошибок

Выходных токенов

До первого файла

medium

37,5 мин

16 / 2

12,8 тыс.

—

low

72,0 мин

27 / 3

29,8 тыс.

—

xhigh

92,8 мин

41 / 4

53,4 тыс.

23 мин

off

оборван на 68 мин

32 / 6

10,3 тыс.

—

Больше всего меня заинтересовал xhigh. У MTPLX на нём было 13 вызовов, 0 ошибок, 27 тыс. токенов и 9 минут до первого файла. На oMLX агент сделал заметно больше работы. Это уже не похоже на один и тот же ответ, который один сервер просто выдаёт медленнее.

По oMLX у меня один прогон на режим. В первой части даже на MTPLX разброс одного и того же medium доходил до 10–16 минут. Так что таблица показывает результат именно этих запусков, устойчивого соотношения скоростей она пока не даёт.

Откуда разница в 3–6 раз

До первого файла на MTPLX прошло 9 минут, на oMLX — 23. Примерно в 2,5 раза дольше. В агентной работе MTPLX выдавал около 34 токенов в секунду; для oMLX оценка по объёму размышлений и затраченному времени была порядка 13.

Соблазнительно назвать это чистым выигрышем от MTP, но время до файла включает ещё и обработку входного контекста и зависит от того, сколько модель решила думать. Эти наблюдения согласуются с более быстрой генерацией на MTPLX, но вклад MTP отдельно они не измеряют.

Дальше траектории расходятся ещё сильнее. У oMLX на xhigh получилось 53 тыс. токенов и 41 шаг против 27 тыс. и 13 шагов на MTPLX. По токенам прогон примерно вдвое длиннее, по числу вызовов — втрое с лишним. Это пересекающиеся части одной работы, поэтому перемножать их нельзя: 2,5 × 1,97 дало бы 4,9, а не 6,4. Каждый лишний шаг на медленном сервере стоит дороже, отсюда и рост разрыва, но точное разложение требует разбивки времени по запросам и инструментам, которой у меня нет. Возможно, oMLX просто досталась неудачная попытка: та же модель на том же шаблоне не обязана отвечать вдвое многословнее.

Режим размышлений на медленном сервере

На MTPLX разница между medium и xhigh терялась в разбросе. На oMLX в этих запусках она большая: medium закончил за 37 минут, xhigh — за 93, low — за 72.

medium оказался в 2,5 раза быстрее родного xhigh при том же результате на тестах. Для меня это повод повторить сравнение: пока нельзя отделить влияние режима от удачной или неудачной попытки.

С low ожидаемой экономии снова не вышло — он проиграл medium на обоих серверах. Объяснение «меньше подумал, дольше исправлял» выглядит правдоподобно, но эта таблица его не доказывает.

Без размышлений

Режим off не довёл задачу до рабочего состояния ни в одной из этих попыток, и провалы получились разными. На MTPLX к 8,5 минуте код даже не импортировался. На oMLX к 68-й минуте в нём был бесконечный цикл: тесты зависли, вместе с ними остановилась работа агента — у инструмента bash в pi нет таймаута, так что прогон я оборвал вручную. Сравнивать эти времена как скорость решения бессмысленно: решения нет, а в ожидание oMLX попало ещё и зависание тестов.

Шум

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

Режим MTPLX

Генерация

Вентиляторы под нагрузкой

Пик температуры

профиль turbo + вентиляторы smart (по умолчанию)

35,1 ток/с

~7 850 об/мин — максимум, с первой секунды

107 °C

turbo + вентиляторы default (управляет macOS)

24,7 ток/с

~5 350 об/мин, разгон за ~30 с

116 °C

sustained + вентиляторы default

19,6 ток/с

~5 350 об/мин

115 °C

В простое вентиляторы крутятся на 2 300–2 500 об/мин, максимум у этой модели ноутбука — около 7 800.

В режиме smart MTPLX сразу выводит их на максимум, ещё до нагрева. Если управление получает macOS, обороты под нагрузкой падают примерно на треть, а генерация проседает на 30%. Температура при этом выше. Похоже на ограничение скорости из-за нагрева, но частоты в этом замере я не снимал.

От sustained пользы я здесь не вижу: обороты те же, что у turbo под управлением macOS, а генерация медленнее ещё на пятую часть. В первой части я упоминал этот профиль как вариант, если мешает шум; замер такого преимущества не показал.

Громкость я не измерял — в таблице обороты, и по ним нельзя установить, насколько тише ноутбук звучит. Отдельного замера шума на oMLX тоже не было.

Память

Второй вопрос из комментариев: сколько всё это съедает и что делать на 24 ГБ.

В этой задаче агент набирал 26–40 тыс. токенов за запрос — системный промпт pi и описания инструментов, спецификация, код и вывод тестов. Окно в 262 тыс. при этом заполнялось на 10–15%.

Контекст у этой модели дешёвый. Внимание гибридное: полный KV-кеш, где хранятся данные внимания для уже обработанных токенов, есть только у 16 слоёв из 64. Один токен стоит около 64 КБ — 40 тыс. токенов это примерно 2,6 ГБ, всё окно в 262 тыс. — около 16 ГБ. Это расчёт, а не замер, и он чувствителен к формату кеша и округлению единиц.

Для oMLX есть замер во время прогона: процесс занимал 18 ГБ, на пике — 21 ГБ. Для MTPLX отдельного замера нет. По его собственному плану памяти выходят 20,7 ГБ весов, около 3 ГБ служебных буферов и KV-кеш по фактическому контексту — на этой задаче всего порядка 26 ГБ. Напрямую сопоставлять это с памятью процесса oMLX я бы не стал: одна цифра измерена, другая рассчитана.

На Mac с 24 ГБ всё сложнее. macOS отдаёт GPU примерно две трети–три четверти памяти, то есть 16–18 ГБ. При таком бюджете плотная 27B в 4 битах вместе с контекстом уже не помещается. На машине с таким объёмом памяти я эту связку не проверял. Из меньших вариантов есть модели класса 9B: для Qwen3.5-9B с MTP команда MTPLX указывает потребность от 16 ГБ. Другой вариант по размеру весов — Ternary-Bonsai-27B в 2 битах, 8,5 ГБ. Их качество на этой задаче здесь не измерено.

А Flash-Next?

В комментариях предложили попробовать Qwen3.8-Flash-Next: это MoE-модель (mixture of experts, смесь экспертов), у которой на каждый токен работает лишь малая часть весов, так что генерация должна быть заметно быстрее. Проверить это мне пока не удалось.

Полные 4-битные сборки весят 106–115 ГБ, а лимит памяти GPU на Mac со 128 ГБ — около 103–107 ГБ, так что места для них и контекста мало. По объёму реалистичнее урезанная REAP-сборка на 73,5 ГБ. До неё я не добрался: на моём канале загрузка заняла бы около 17 часов. Пока это кандидат для следующей части, без замеров скорости и качества.

Грабли

Окно контекста по умолчанию. oMLX из коробки ограничивает контекст 32 768 токенами. Для агента этого впритык: задача из статьи набирала до 40 тыс. Параметр max_context_window в настройках oMLX стоит проверить сразу.

Ключ API. oMLX требует ключ. В models.json pi его можно вписать прямо текстом, но удобнее другой вариант: pi умеет брать ключ командой — "apiKey": "!команда, которая печатает ключ". Тогда ключ живёт только в настройках самого oMLX и не дублируется.

Встроенный бенчмарк обрывает работу. Это тот оборванный прогон, о котором я писал в первой части, отдельно от завершённых попыток выше. В админке запустили встроенный бенчмарк, и тот мгновенно выгрузил модель, прервав запрос агента. pi получил «Connection error» и провисел до таймаута.

SSD-кеш растёт молча. У oMLX кеш обработанных промптов на SSD включён по умолчанию и за пару дней тестов вырос до 17 ГБ. У MTPLX я включал такой кеш для экспериментов — за то же время он дорос до 51 ГБ. Ускорения на этой задаче он не дал ни там, ни там: внутри сессии историю и так держит кеш в оперативной памяти.

Оба сервера — на порту 8000. Если держать оба, одному придётся сменить порт. MTPLX при занятом порту уходит в «ограниченный режим» и теряет связь со своим же сервером.

Запуск из образа DMG. Как и MTPLX, oMLX легко запустить прямо из смонтированного .dmg. Работает до первого отмонтирования образа.

Своя ошибка методики. Однажды я назвал папку первого прогона на oMLX по режиму, которого в нём не было, и следующий прогон в medium пришёл в папку с уже готовым решением. Он «решил» задачу за 8 минут — и этот результат пришлось выбросить.

Выводы

  • MTP на этой задаче ускоряет генерацию, и связка MTPLX закончила быстрее oMLX в 2,8–6,4 раза. Но записывать всю разницу на счёт MTP не стану: траектории агента разошлись, и у oMLX на xhigh работы оказалось заметно больше. Совет ChatGPT взять oMLX как решение «быстрее и качественнее» на этом железе не подтвердился — по качеству связки сравнялись, по скорости проиграла именно oMLX.

  • Качество в этих прогонах определилось моделью, а не сервером: во всех завершённых режимах с размышлениями обе связки прошли 30 из 30 скрытых тестов. На других задачах это утверждение не проверено.

  • На медленном сервере режим размышлений важнее. medium на oMLX оказался в 2,5 раза быстрее родного xhigh при том же результате; на быстром MTPLX эта разница тонет в разбросе.

  • Выключенные размышления не довели задачу до рабочего состояния ни на одном из серверов.

  • Тише — значит медленнее, и почти один к одному: перевод вентиляторов под управление macOS срезал обороты примерно на треть и скорость генерации примерно на столько же. Профиль sustained тише не сделал.

  • По oMLX у меня один прогон на режим, поэтому я не берусь утверждать, что xhigh всегда в два с половиной раза дороже medium: нужны повторы.

Если вам интересна третья часть — напишите в комментариях, что проверять: Flash-Next на урезанной сборке, реальный репозиторий вместо синтетической задачи или что-то ещё.

Комментарии (0)