Ollama медленно генерирует токены: причины и решение
Модель выдаёт по слову в секунду, курсор ползёт, а htop показывает загрузку процессора в 30% — знакомая картина. Ollama почти никогда не «тормозит сама по себе»: за медленной генерацией стоит одна из четырёх конкретных причин, и каждая диагностируется за пару минут. Разберём, как найти свою по цифрам, а не по ощущениям, и что реально даёт прирост, а что плацебо.
Содержание
- Сначала цифры: `--verbose` и eval rate
- Скорость упирается не в ядра, а в пропускную способность памяти
- Модель не поместилась: частичная выгрузка и своп
- Квантование: сколько стоит каждый лишний бит
- Контекст и KV-кэш — тихий пожиратель скорости
- Перезагрузка модели, keep_alive и лишний параллелизм
- Какой сервер брать под Ollama в MAATRIX
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Сначала цифры: `--verbose` и eval rate
Пока нет числа токенов в секунду, обсуждать нечего. Ollama показывает его сам — запустите модель с флагом и задайте вопрос:
ollama run llama3.1:8b --verbose
После ответа вы увидите блок статистики:
total duration: 1m12.445s
load duration: 8.214s
prompt eval count: 1462 token(s)
prompt eval duration: 31.208s
prompt eval rate: 46.85 tokens/s
eval count: 412 token(s)
eval duration: 33.021s
eval rate: 12.48 tokens/s
Читать это надо так:
load duration— загрузка весов с диска. Заметной должна быть только в первом запросе; если она в каждом — модель выгружается между ними, это шестая секция.prompt eval rate— обработка вашего промпта. Считается пакетно, упирается в вычисления: на CPU это 30–60 tok/s, на GPU — тысячи.eval rate— собственно генерация, строго по одному токену. Именно эта цифра и есть «скорость Ollama».
Тормозят они по разным причинам: задержка в prompt eval duration лечится кэшем префикса и коротким системным промптом, а низкий eval rate — это память, и ядра тут не помогут. Для мониторинга те же поля отдаёт API: в ответе /api/generate есть eval_count и eval_duration в наносекундах.
Запишите полученное число. Норма для вашего железа считается в следующей секции: попали в неё — ускорять надо железо, вдвое ниже — ищите потерю в разделах 3–6.
Скорость упирается не в ядра, а в пропускную способность памяти
Главное про инференс: чтобы выдать один токен, движок обязан прочитать все веса модели. Модель 8B в Q4_K_M — это 4,9 ГБ через шину памяти на каждый токен. Отсюда потолок:
eval rate ≈ пропускная способность памяти ÷ размер весов × 0,6–0,75
Коэффициент — КПД реальной системы против паспорта. Подставляем:
| Память | Пиковая полоса | 8B Q4_K_M (4,9 ГБ) | 70B Q4_K_M (40 ГБ) |
|---|---|---|---|
| DDR4-3200, 2 канала | 51 ГБ/с | 6–9 tok/s | 0,7–1 tok/s |
| EPYC, 8 каналов DDR4-3200 | 205 ГБ/с | 25–33 tok/s | 3–4 tok/s |
| RTX 4090, GDDR6X | 1008 ГБ/с | 110–140 tok/s | не помещается |
| A100 80 ГБ, HBM2e | 2039 ГБ/с | 180–250 tok/s | 25–35 tok/s |
Два следствия. Первое: переход с 8 vCPU на 16 почти ничего не даёт, если каналы памяти те же — полоса не выросла, потолок остался (разбор в статье Ollama не использует все ядра CPU). Второе: разрыв между CPU и GPU — не «в два раза», а в 15–20 раз, и он структурный.
Свою полосу измерьте так: sysbench memory --memory-block-size=1M --memory-total-size=32G --memory-oper=read --threads=8 run. На здоровом двухканальном DDR4 будет 30 000–45 000 MiB/sec. Сильно меньше — вы на переподписанном узле и делите шину с соседями. Полосу памяти нельзя «настроить», её можно только купить другую.
Развернуть за пару минут
Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть OllamaМодель не поместилась: частичная выгрузка и своп
Самая частая причина «было 120 tok/s, стало 9» — модель перестала помещаться целиком, и часть слоёв уехала на CPU. Проверяется командой ollama ps:
NAME ID SIZE PROCESSOR UNTIL
llama3.1:8b 46e0c10c039e 11 GB 38%/62% CPU/GPU 4 minutes from now
Строка 38%/62% CPU/GPU — это диагноз. Скорость связки определяет медленная половина: даже 20% слоёв на процессоре срезают генерацию со 130 до 20–25 tok/s. Промежуточного не дано: либо модель целиком в VRAM, либо это CPU с надбавкой.
Решение планировщика видно в журнале — sudo journalctl -u ollama -n 200 --no-pager | grep -i offload:
level=INFO source=server.go:168 msg=offload library=cuda layers.requested=-1
layers.model=33 layers.offload=21 memory.available="[11.6 GiB]"
memory.required.full="15.1 GiB" memory.required.partial="11.2 GiB"
Нужно 15,1 ГиБ, свободно 11,6 — в видеопамять уехал 21 слой из 33. Дальше арифметика: уменьшить memory.required.full (квантование, контекст, KV-кэш) либо увеличить memory.available. Проверьте заодно nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv: часто VRAM занял посторонний процесс.
На CPU-сервере аналог этой беды — своп: когда памяти не хватает, ядро возит страницы на диск, и генерация падает до долей токена в секунду. Смотрите vmstat 1 во время запроса:
r b swpd free buff cache si so bi bo us sy id wa st
2 1 3145728 98432 1204 512300 21504 18432 42112 19200 18 9 6 67 0
Ненулевые si/so и wa под 67% — модель живёт в свопе. Настройками не лечится: либо модель меньше, либо больше RAM. «Добавить своп побольше» не работает: NVMe медленнее DDR4 примерно в сто раз. Если памяти не хватает совсем, Ollama скажет прямым текстом: Error: model requires more system memory (9.3 GiB) than is available (5.1 GiB). Сколько её нужно на какую модель — таблица в материале Сколько RAM нужно для Ollama.
Квантование: сколько стоит каждый лишний бит
Раз скорость обратно пропорциональна размеру весов, квантование — самый дешёвый рычаг. Проверьте, что скачано:
ollama show llama3.1:8b
Model
architecture llama
parameters 8.0B
context length 131072
quantization Q4_K_M
Тег без суффикса даёт Q4_K_M — разумный дефолт. Но люди регулярно тянут :8b-instruct-q8_0 «чтобы получше» и получают вдвое меньшую скорость. Замеры на одном сервере с 8 vCPU и DDR4-3200:
| Квантование | Размер файла | eval rate | Качество |
|---|---|---|---|
q8_0 | 8,5 ГБ | 3,5 tok/s | эталон |
q6_K | 6,6 ГБ | 4,6 tok/s | отличий почти нет |
q5_K_M | 5,7 ГБ | 5,4 tok/s | отличий почти нет |
q4_K_M | 4,9 ГБ | 6,8 tok/s | рабочий баланс |
q3_K_M | 4,0 ГБ | 8,1 tok/s | заметно деградирует |
Честный вывод: выше Q6 платить за качество бессмысленно, ниже Q4_K_M — опасно. Первым при агрессивном сжатии ломается код, следом — работа с числами и длинными инструкциями. Не влезает в Q4_K_M — берите модель поменьше в Q4, а не ту же в Q3: 8B в Q4_K_M осмысленнее, чем 14B в Q3_K_S. Переключение — ollama pull llama3.1:8b-instruct-q4_K_M и ollama rm для старого тега.
Контекст и KV-кэш — тихий пожиратель скорости
Второй по частоте случай «сам себе навредил»: человек ставит num_ctx в 32768 на всякий случай и удивляется, куда делась скорость. Дело в KV-кэше — он занимает память дополнительно к весам и растёт линейно по длине контекста.
Для Llama 3.1 8B (32 слоя, 8 KV-голов, размерность головы 128, кэш в fp16) на один токен уходит 32 × 8 × 128 × 2 × 2 = 131 072 байта, ровно 128 КиБ. Дальше просто:
| Контекст | KV-кэш fp16 | KV-кэш q8_0 |
|---|---|---|
| 4 096 | 0,5 ГиБ | 0,25 ГиБ |
| 8 192 | 1 ГиБ | 0,5 ГиБ |
| 32 768 | 4 ГиБ | 2 ГиБ |
| 131 072 | 16 ГиБ | 8 ГиБ |
Те самые 4 лишних гигабайта на карте с 12 ГБ VRAM и выталкивают треть слоёв на процессор. По умолчанию Ollama берёт 4096 токенов; если надо больше — поднимайте ровно до нужного, а не до максимума модели:
OLLAMA_CONTEXT_LENGTH=8192
В интерактивной сессии — /set parameter num_ctx 8192, через API — "options": {"num_ctx": 8192}. Переменная OLLAMA_CONTEXT_LENGTH доступна начиная с 0.6, проверьте свою через ollama -v.
Второй рычаг — квантование самого кэша: требует включённого flash attention и режет память вдвое (q8_0) или вчетверо (q4_0):
OLLAMA_FLASH_ATTENTION=1
OLLAMA_KV_CACHE_TYPE=q8_0
q8_0 на практике неотличим от fp16 — берите смело. q4_0 экономит больше, но на длинных диалогах модель теряет детали из начала контекста: для чата терпимо, для работы с документами — нет.
Отдельно про prompt eval count: если в продолжении диалога оно равно всей истории, а не десятку новых токенов, кэш префикса не сработал и переписка пересчитывается заново каждый ход. Причины обычно две — меняющийся системный промпт (подставляемая дата, случайный идентификатор) или параллельные слоты, вытесняющие кэш друг друга.
Перезагрузка модели, keep_alive и лишний параллелизм
Вернитесь к load duration из первой секции: если она 8 секунд и появляется в каждом запросе, вы платите их постоянно. По умолчанию Ollama выгружает модель через 5 минут простоя — для сервера, который отвечает раз в десять минут, это худший режим.
Настройки задаются переменными окружения службы. Правильное место — drop-in systemd:
sudo systemctl edit ollama
[Service]
Environment="OLLAMA_KEEP_ALIVE=24h"
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"
Environment="OLLAMA_CONTEXT_LENGTH=8192"
Environment="OLLAMA_NUM_PARALLEL=1"
Environment="OLLAMA_MAX_LOADED_MODELS=1"
sudo systemctl daemon-reload && sudo systemctl restart ollama
systemctl show ollama --property=Environment
Последняя команда обязательна — она показывает, что переменные доехали до процесса. Половина случаев «не помогло» это экспорт в ~/.bashrc: служба стартует не из вашего шелла.
Что делает каждая строка:
OLLAMA_KEEP_ALIVE=24h— модель остаётся в памяти (-1— бесконечно). Обратная сторона: занятая VRAM никому больше не достанется.OLLAMA_NUM_PARALLEL=1— Ollama готовит несколько слотов параллельных запросов, и объём KV-кэша умножается на их число. Для одного клиента это потеря памяти и повод выгрузить слои на CPU.OLLAMA_MAX_LOADED_MODELS=1— две модели в VRAM вытесняют друг друга, иload durationвозвращается при каждом переключении.
Веса лежат в /usr/share/ollama/.ollama/models (при ручном запуске — в ~/.ollama/models). NVMe читает их на 1,5–3 ГБ/с и поднимает модель 5 ГБ за 2–4 секунды, сетевое хранилище на 150 МБ/с — за полминуты.
Какой сервер брать под Ollama в MAATRIX
Честный минимум для CPU-инференса: 8 vCPU, 16 ГБ RAM, NVMe. Модель 8B в Q4_K_M с контекстом 8k выдаёт на нём 6–9 tok/s — хватает для фоновых задач: суммаризация, классификация писем, разбор документов по расписанию, локальный RAG. Для живого чата это медленно, и притворяться иначе смысла нет.
Память считайте по формуле вес модели + KV-кэш + 2 ГБ на систему плюс запас на страничный кэш. Для 8B с контекстом 8k выходит 4,9 + 1 + 2 ≈ 8 ГБ, но брать надо 16 ГБ, иначе веса вымываются из кэша. Для 14B комфортно 32 ГБ, для 32B — 64 ГБ, но там скорость на CPU падает до 2–3 tok/s, и это уже разговор про GPU.
Комфортный вариант — сервер с видеокартой, где VRAM больше суммы «веса + KV-кэш». 24 ГБ закрывают 8B–14B на полной скорости и 32B в Q4 впритык. Разница не косметическая: 8–9 tok/s против 110–140. Для интерактивного интерфейса и нескольких пользователей альтернатив, по сути, нет, а на десятках параллельных запросов смотреть надо уже не на Ollama — сравнение в материале Ollama против vLLM.
Локация под эту задачу — UK, Лондон, по двум прикладным причинам. Первая: веса с реестра качаются на полной скорости канала, модель 20 ГБ приезжает за минуты, а не за вечер. Вторая: пинг из Москвы до Лондона 45–60 мс — для потоковой отдачи токенов незаметно, зато клиентам из ЕС минимальная задержка и GDPR-контур. Франция закрывает тот же сценарий, российская площадка нужна при требованиях 152-ФЗ, американская — если рядом живёт ещё и прокси к внешним ИИ-API.
До заказа снимите eval rate с --verbose и посмотрите ollama ps: упор в настройки — половина статьи решает вопрос бесплатно, упор в железо — конфигурацию соберём под конкретную модель, а не «на глаз». Оплата картой российского банка, по СБП, криптой или токеном MAAT; иностранная карта для зарубежной площадки не нужна. Базовая установка разобрана в статье Как поднять локальный запуск LLM через Ollama.
Оговорка напоследок: на общем VPS с переподпиской eval rate плавает на ±30% в зависимости от соседей по узлу. Нужна предсказуемая скорость — берите тариф с выделенными ядрами или отдельный сервер.
Развернуть за пару минут
Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть OllamaОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
Ollama медленно работает — поможет ли добавить vCPU?
Почти нет. Генерация упирается в пропускную способность памяти, а не в вычисления: переход с 8 ядер на 16 при тех же каналах памяти даёт единицы процентов. Помогает больше каналов памяти или GPU.
Почему первый ответ идёт 10 секунд, а следующие быстро?
Это load duration — загрузка весов с диска. По умолчанию модель выгружается через 5 минут простоя; поставьте OLLAMA_KEEP_ALIVE=24h через systemctl edit ollama, и задержка исчезнет.
Я поднял контекст до 32k, и скорость упала втрое. Это баг?
Нет. KV-кэш вырос на несколько гигабайт, модель перестала помещаться в VRAM, и часть слоёв уехала на CPU — это видно в ollama ps как 38%/62% CPU/GPU. Верните контекст к реально нужному и включите OLLAMA_KV_CACHE_TYPE=q8_0.
Нужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.