Три типичных боли. (1) Внезапный OOM после увеличения num_ctx или второго клиента — KV и активации съедают тот же пул, что и веса. (2) Несопоставимые прогоны: другой GGUF или другая сборка дают иной throughput при тех же «логических» настройках. (3) Деградация со временем из‑за термодросселя и фонового давления памяти, которую ошибочно списывают на «качество модели». Для пайплайнов с эмбеддингами и индексацией см. связанный материал о локальном RAG и батчах эмбеддингов; обзор площадки — на главной, каталог аренды — страница покупки.
На странице: аппаратные границы · GGUF и квантование · конкурентность и батч · FAQ по стабильности
Аппаратные границы
У Mac на M4 одна унифицированная память обслуживает и CPU, и GPU через общий контроллер: эффективная полоса высокая, но бюджет фиксирован. Веса в GGUF, буфер KV для длинного контекста, батч decode и временные тензоры префилла конкурируют за мегабайты одновременно. Рост окна контекста увеличивает объём KV приблизительно пропорционально длине последовательности и числу слоёв; на практике переход с 8k к 128k токенов при той же модели может быть невозможен без смены кванта или машины.
Ориентиры для планирования. Считайте, что пиковая нагрузка приходит в фазе префилла и при первом расширении батча; стабильный decode дешевле, пока не упираетесь в термалы. Используйте мониторинг давления памяти и снимайте пик RSS вместе с версией macOS и билдом рантайма — иначе регрессии не воспроизвести.
- Полоса памяти: упираетесь в неё при широком батче и длинных векторах скрытого состояния; свап на APFS резко режет интерактивную задержку.
- Термалы: удерживайте устойчивый режим вентиляции; длительные ночные прогоны на закрытом ноутбуке часто ударяют по троттлингу раньше, чем по «логике» модели.
- Изоляция: отдельный пользователь или отдельный узел для экспериментов снижает риск, что фоновый браузер съест запас по памяти.
GGUF и выбор квантования
Файл GGUF — переносимый контейнер весов; llama.cpp читает его напрямую, Ollama — через свой стек, но физика памяти та же. Q4_K_M обычно компромисс качество/объём для чата; Q8_0 ближе к полной точности, но сильнее сужает запас под KV и параллель. Экзотические IQ-варианты экономят байты ценой нестабильного перцептивного качества — их стоит сравнивать на вашем золотом наборе промптов, а не по одному ответу.
Зафиксируйте в runbook: имя файла, SHA-256, семейство кванта и целевое num_ctx. Любое обновление Ollama или llama.cpp перепроверяйте коротким регрессионным прогоном на десятке эталонных запросов. Если эмбеддер и чат делят одну машину, суммируйте их пики — здесь же пригодится матрица квот и батчей для RAG.
# Пример: явный контекст и один поток для воспроизводимого бенчмарка (llama.cpp)
llama-cli -m model.Q4_K_M.gguf -c 8192 -b 512 -ngl 99 --simple-ioКонкурентность и размер батча
llama.cpp даёт прямой контроль: флаги вроде -b для батча decode, размер контекста через -c, offload слоёв на GPU через -ngl. Несколько процессов — несколько копий весов в RAM, если не используете общий сервер. Ollama абстрагирует часть деталей, но параллельные запросы и окно контекста по-прежнему умножают память; переменные окружения вроде OLLAMA_NUM_PARALLEL и параметры модели задают поведение планировщика.
Ниже — сводная таблица для сопоставления ручек (значения ориентировочные; уточняйте прогоном на вашей модели и объёме памяти).
| Параметр / вопрос | llama.cpp | Ollama | Заметка для M4 |
|---|---|---|---|
| Окно контекста (KV) | -c / --ctx-size |
num_ctx в Modelfile или API |
Длинный контекст — главный рычаг потребления памяти наряду с квантом. |
| Батч decode (ширина токенов) | -b; для сервера — аналоги в API |
Автоподбор + лимиты сервера | Широкий батч повышает throughput, но быстрее упирается в полосу и RAM. |
| Параллельные сессии | Несколько процессов или llama-server | OLLAMA_NUM_PARALLEL |
Каждая сессия добавляет собственный KV; следите за суммарным RSS. |
| Offload на GPU | -ngl (число слоёв) |
По умолчанию максимально возможный Metal-путь | Полный offload уменьшает копии на CPU, но не отменяет лимит unified memory. |
| Диагностика узкого места | --verbose, лог eval префилла |
Логи сервиса, метрики задержки | Разделяйте стоимость префилла и стабильный decode по латентности. |
Пошаговая настройка (минимум пять шагов):
- Закрепить файл GGUF и версии llama.cpp или Ollama в заметке к проекту.
- Прогнать один длинный запрос с целевым контекстом, записать токены в секунду и пик памяти.
- Увеличить контекст ступенями до появления заметной задержки или предупреждений Metal — откатить на ступень назад.
- Добавить второй параллельный клиент или поднять батч; найти точку, где прирост скорости не стоит swap.
- Зафиксировать итоговые флаги и переменные окружения в скрипте запуска или CI.
- Для сценариев «ночью крутить большой контекст» перенести нагрузку на выделенный удалённый Mac с известным объёмом памяти и без личных приложений.
Чек-лист перед продакшн-нагрузкой:
- Проверены хеш GGUF и ревизия рантайма; есть контрольный набор промптов.
- Задокументированы
num_ctx, параллель и батч; известен запас до pressure yellow/red. - Отключены тяжёлые фоновые приложения на интерактивной машине или нагрузка вынесена на арендованный узел.
- Есть план отката: более мелкий квант или меньшее окно без пересборки всего стека.
Короткие факты для ссылок в отчётах: (1) KV растёт с числом слоёв и длиной контекста — это чаще лимитирует длину диалога, чем «голые» веса. (2) Широкий батч в первую очередь бьёт по пропускной способности памяти при крупных скрытых размерностях. (3) Unified memory означает, что конкуренцию за гигабайты выигрывает тот стек, который вы измерили последним — браузер и IDE тоже в счёте.
FAQ по стабильности
Деградация через несколько минут. Проверьте термальный троттлинг и давление памяти; снизьте параллель или контекст, улучшите охлаждение, закройте тяжёлые вкладки.
Разный throughput у Ollama и llama.cpp. Нормально при разных дефолтах и версиях движка; сравнивайте на одном GGUF и с явно заданным контекстом.
Metal OOM при длинном чате. Сначала уменьшите окно или квант; убедитесь, что не запущено двух копий модели; для редких длинных сессий используйте узел с большим объёмом памяти.
Нужен ли фиксированный seed в проде? Для пользовательского чата обычно нет; для регрессионных тестов и отчётов перед аудитом — да, с логированием температуры и top_p.
Итог: сначала квант и контекст, затем батч и параллель; всё измерять на реальной машине с логом версий. Длинные и тяжёлые прогоны разумнее изолировать на удалённом Mac mini, оставив локальный M4 под интерактив и разработку.