MAATRIX / Блог / llama.cpp против Ollama: что выгоднее и когда

llama.cpp против Ollama: что выгоднее и когда

llama.cpp против Ollama: что выгоднее и когда

MAATRIX

Спор «llama cpp или ollama» выглядит как выбор между двумя движками, но выбираете вы между движком и продуктом вокруг него: Ollama считает теми же ядрами ggml. Разница почти не в скорости — она в том, кто управляет контекстом, потоками и обновлениями, и во что это обходится в эксплуатации. Ниже — граница выбора, команды сборки, точные тексты ошибок и расчёт сервера.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Короткий ответ: где проходит граница

Разложите решение на три вопроса — и выбор займёт минуту.

  • Сколько у вас моделей. Нужно держать чат на 8B, мелкую модель для классификации и эмбеддинги, переключаясь между ними по требованию, — берите Ollama. Один процесс llama-server обслуживает ровно одну модель, и мультимодельность придётся собирать самому.
  • Насколько важен контроль над сборкой и флагами. Нужны поддержка только что вышедшей архитектуры, квантованный KV-кэш, точный --parallel, сборка под конкретные инструкции процессора — это llama.cpp. Ollama прячет половину этих ручек за умолчаниями.
  • Кто будет это обслуживать. Ollama ставится одной командой, обновляется пакетом, сама скачивает модели и переживает перезагрузку без вашего участия. llama.cpp — это бинарник, который вы собрали, юнит systemd, который вы написали, и обновление руками.

Короче: Ollama выгоднее, когда моделей много, а времени мало; llama.cpp — когда модель одна, а требования к ней жёсткие. И честно: разницы в токенах в секунду при одинаковой модели, квантовании и числе потоков вы почти не увидите — внизу один и тот же ggml.

И сразу отсечём ложную развилку: ни один из них не про высокий параллелизм. Если к модели постоянно приходит десяток одновременных запросов, ответ не «llama.cpp», а vLLM с видеокартой — разбор в статье Ollama против vLLM.

Что вы на самом деле сравниваете

llama.cpp — проект ggml-org: библиотеки ggml плюс исполняемые файлы. После переименования 2024 года они называются llama-cli, llama-server, llama-bench, llama-quantize и лежат в build/bin/. Инструкции с ./main и ./server устарели: таких бинарников больше нет.

Семантических версий у llama.cpp нет. Релиз — это номер сборки вида b10154, и выходит их по нескольку в день. Следствие: «последняя версия» у вас и у автора инструкции — разные сборки, а флаги между ними меняются. Свежий пример — --flash-attn, который из переключателя стал принимать on, off и auto.

Ollama — сервер на Go с реестром моделей, CLI и HTTP-API, версии обычные, вида 0.33.x. Долгое время это была обвязка вокруг llama.cpp, но формулировка «Ollama — это просто llama.cpp» уже неточна: часть моделей обслуживает её собственный движок поверх ggml, минуя код llama.cpp. Отсюда расхождение в наборе поддерживаемых архитектур: «в llama.cpp эта модель уже работает» не гарантирует, что она работает в Ollama, и наоборот.

Лицензия у обоих MIT — юридических поводов выбирать нет. А языки разные, и это заметно: Ollama — один бинарник на Go без зависимостей, llama.cpp — C++, который надо собрать под вашу систему.

llama.cppOllama
Что этодвижок и набор бинарниковсервер с реестром моделей
Установкасборка через cmake или готовый архивinstall.sh, deb-репозиторий, Docker
Версионированиеномер сборки bNNNNN0.33.x
Моделей на процессоднанесколько, с выгрузкой по таймауту
Формат моделейфайлы .gguf как естьblob-хранилище с манифестами
Авторизация в API--api-key из коробкинет, только через обратный прокси
Порт по умолчанию8080, слушает 127.0.0.111434, слушает 127.0.0.1
Веб-интерфейсвстроенный, отключается --no-webuiнет, ставится отдельно

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Установка и обновление: одна команда против cmake

Ollama ставится так, и на этом всё:

curl -fsSL https://ollama.com/install.sh | sh
systemctl status ollama
ollama pull qwen2.5:7b

Скрипт заводит пользователя ollama, кладёт юнит в /etc/systemd/system/ollama.service и включает автозапуск; модели уезжают в /usr/share/ollama/.ollama/models.

llama.cpp собирается из исходников. На чистой Ubuntu 24.04 нужен полный набор зависимостей:

apt update && apt install -y build-essential cmake git libcurl4-openssl-dev
git clone https://github.com/ggml-org/llama.cpp && cd llama.cpp
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release -j "$(nproc)"

Две ошибки, на которых спотыкаются практически все.

Забытый libcurl. Скачивание моделей по -hf встроено в общий код, и без заголовков curl конфигурация просто падает:

CMake Error at common/CMakeLists.txt:90 (message):
  Could NOT find CURL (missing: CURL_LIBRARY CURL_INCLUDE_DIR)

Лечится либо apt install libcurl4-openssl-dev, либо флагом -DLLAMA_CURL=OFF, если модели вы кладёте на диск руками.

Illegal instruction после переезда. По умолчанию сборка идёт с GGML_NATIVE=ON — под инструкции того процессора, на котором вы собирали. Пока машина та же, всё хорошо; после живой миграции на узел с более старым CPU или переноса бинарника получаете:

Illegal instruction (core dumped)

Ни строчки объяснения, ни лога. Если бинарник переезжает между машинами, собирайте с -DGGML_NATIVE=OFF и явным набором расширений вроде -DGGML_AVX2=ON: потеря скорости — единицы процентов.

Собирать не обязательно: готовые архивы лежат в релизах (llama-b10154-bin-ubuntu-x64.zip — распаковать и запускать, если glibc не старше сборочной), есть официальный образ ghcr.io/ggml-org/llama.cpp:server, и тогда обновление сводится к смене тега.

Обновление — самая недооценённая статья расходов. Ollama обновляется повторным запуском install-скрипта, юнит и модели остаются на месте. llama.cpp — вручную: git pull, пересборка (на 4 vCPU несколько минут под полной загрузкой), подмена бинарника. Раз в квартал терпимо, раз в неделю — уже работа.

Деталь про наш каталог: Ollama есть в apps.maatrix.io и разворачивается автоматически при заказе сервера, доступы приходят в кабинет. llama.cpp в каталоге нет — сервер приезжает чистым, и вы ставите её по командам выше: одного «правильного» набора флагов сборки у неё не существует.

Модели: файлы GGUF против blob-хранилища

llama.cpp работает с обычными файлами. Скачали .gguf с Hugging Face — указали путь в -m. Есть и встроенная загрузка:

./build/bin/llama-server -hf bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M -c 8192

Ollama хранит модели иначе: содержимое лежит в blobs/ под именами sha256-... без расширения, состав описан манифестом в manifests/registry.ollama.ai/library/. Тег qwen2.5:7b — указатель, который может переехать на другую сборку; воспроизводимо выглядит qwen2.5:7b-instruct-q4_K_M.

Отсюда ловушка с диском. Если вы уже держите GGUF-файлы для llama.cpp и импортируете те же модели в Ollama, ollama create не ссылается на файл, а копирует его в своё хранилище: 5 ГБ весов превращаются в 10 ГБ. На 40–60 ГБ NVMe три-четыре такие пары упираются в no space left on device быстрее, чем кажется.

Работает и обратный, более полезный трюк. Ollama печатает реальный путь к весам, и его можно скормить llama.cpp — без повторной загрузки и без дубликата:

ollama show --modelfile qwen2.5:7b | awk '/^FROM/{print 

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

; exit}' # /usr/share/ollama/.ollama/models/blobs/sha256-2bada8a74506... ./build/bin/llama-server -m "$(ollama show --modelfile qwen2.5:7b | awk '/^FROM/{print

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

; exit}')" \ -c 8192 -t 8 --host 127.0.0.1 --port 8080

Так вы сравниваете два сервера на одном и том же файле — и заодно снимаете вопрос «перекладывания» моделей при переходе с одного инструмента на другой.

Где хранить — тоже разница. У Ollama путь меняется переменной OLLAMA_MODELS, и задать её надо до первой загрузки, иначе блобы придётся переносить руками. У llama.cpp вопроса нет: файл лежит там, где вы его положили. Про выбор квантования — отдельный разбор в статье Какое квантование выбрать для Llama.

Скорость и память: чего ждать на CPU

Главное принять: на одинаковых входных условиях они считают примерно одинаково. Ниже — наш замер на AMD EPYC 9554, 16 vCPU (8 физических ядер плюс гипертреды), Ollama 0.33.1, qwen2.5:7b в Q4_K_M, контекст 4096.

ПотоковОбработка промпта, ток/сГенерация, ток/с
212,65,7
431,07,6
1668,07,4
3210,90,35

Два вывода, одинаково верных для обоих инструментов. Первый: генерация выходит на полку уже на четырёх потоках — 7,6 против 7,4 на шестнадцати, разница в пределах погрешности. Упирается она не в процессор, а в пропускную способность памяти: на каждый токен читаются все веса целиком. Обработка промпта, наоборот, честно растёт до числа физических ядер — это матричные операции.

Второй: 32 потока на 16 vCPU дают обвал в двадцать раз, до 0,35 токена в секунду. Потоки вытесняют друг друга с ядер, и модель отвечает по три секунды на токен. Ставить -t или num_thread «с запасом» нельзя. Подробнее — в статье Ollama не использует все ядра CPU.

Разброс по моделям на том же стенде при 16 потоках больше, чем разброс между инструментами:

Модель, Q4_K_MГенерация, ток/сЗанято по ollama ps
qwen2.5:3b34,12,2 ГБ
llama3.1:8b12,85,6 ГБ
mistral:7b12,15,0 ГБ
gemma2:9b8,8
qwen2.5:7b7,45,1 ГБ

Обратите внимание: «7B» само по себе не говорит ничего — mistral:7b быстрее qwen2.5:7b почти вдвое. И третью колонку читайте правильно: ollama ps показывает не веса, а всю занятую память — веса плюс KV-кэш и вычислительные буферы. Для 7B в Q4_K_M это ~4,7 ГБ весов и ещё несколько сотен мегабайт сверху при контексте 4096.

А вот управление потоками различается ощутимо. У llama.cpp это флаги запуска: -t 8 на генерацию и -tb 16 отдельно на обработку промпта — обе полки забираются сразу. У Ollama переменной окружения для потоков нет вовсе: num_thread задаётся через PARAMETER в Modelfile, поле options в API или /set parameter. Строка OLLAMA_NUM_THREAD=16 в юните не даст ничего — сервис её молча проигнорирует.

Мерить на своём железе удобнее штатным бенчмарком llama.cpp — ни клиента, ни сервера он не требует:

./build/bin/llama-bench -m ~/models/qwen2.5-7b-instruct-q4_k_m.gguf -p 512 -n 128 -t 8
# столбцы: model | size | params | backend | threads | test | t/s
# строка pp512 — обработка промпта, tg128 — генерация

Контекст, слоты и эксплуатация: где различия становятся дорогими

Самая недооценённая разница — семантика контекста, и на ней теряют память обе стороны, но по-разному.

В llama.cpp -c — это общий бюджет KV-кэша на все слоты. Запустили -c 32768 -np 4 — каждый запрос получит по 8192 токена, а не по 32768. Логика против интуиции, зато память предсказуема: сколько попросили, столько и заняли; поведение регулируется флагом --kv-unified.

В Ollama num_ctx — это контекст на слот, и он умножается. OLLAMA_NUM_PARALLEL=4 при num_ctx 8192 означает запрос кэша на 32768 токенов, независимо от того, пользуется ли кто-то слотами сейчас. Отсюда классическое «поставил 8 на всякий случай — получил нехватку памяти на ровном месте». Плюс своя логика умолчаний: контекст выбирается по доступной памяти, и без видеокарты это обычно 4096 — модель с окном 128k молча работает в 4k, пока вы не скажете обратное.

Когда контекст всё-таки кончается, llama-server отвечает не молчанием, а конкретным HTTP 400:

{"error":{"code":400,"type":"invalid_request_error",
 "message":"the request exceeds the available context size. try increasing the context size or enable context shift"}}

Сдвиг контекста в свежих сборках выключен и включается флагом --context-shift. Ollama обрежет начало диалога сама — удобнее, но вы не узнаете, что модель забыла системный промпт.

Дальше — четыре вещи, которые решают в проде:

  • Держать ли модель в памяти. Ollama выгружает её через 5 минут простоя, и следующий запрос ждёт повторной загрузки весов с диска; лечится OLLAMA_KEEP_ALIVE=-1. llama-server держит модель постоянно — это и плюс (нет холодных стартов), и минус (память занята круглосуточно).
  • Авторизация. У llama-server есть --api-key, и без заголовка Authorization: Bearer запрос не пройдёт. У Ollama её нет: открытый наружу порт 11434 — это чужие люди, гоняющие ваш процессор. Оба слушают localhost, и это правильно: наружу только через Nginx с TLS, плюс ufw deny 11434/tcp и ufw deny 8080/tcp.
  • Несколько моделей. У Ollama это данность: OLLAMA_MAX_LOADED_MODELS и автовыгрузка. У llama.cpp — процесс на модель, разные порты и своя маршрутизация сверху либо прокси вроде llama-swap. Если моделей три, а памяти на одну, выбор сделан за вас.
  • Юнит systemd вы пишете сами. Минимальный рабочий вариант для llama-server:
[Unit]
Description=llama.cpp server
After=network-online.target

[Service]
User=llama
ExecStart=/opt/llama.cpp/build/bin/llama-server \
  -m /opt/models/qwen2.5-7b-instruct-q4_k_m.gguf \
  -c 8192 -np 2 -t 8 -tb 16 --host 127.0.0.1 --port 8080 \
  --api-key-file /etc/llama/apikey --no-webui --metrics
Restart=always
RestartSec=3
LimitMEMLOCK=infinity

[Install]
WantedBy=multi-user.target

Диагностика тоже разная. curl -s 127.0.0.1:8080/health отдаёт {"status":"ok"}, при загрузке весов — 503 с "message":"Loading model"; /props показывает фактический n_ctx, /slots (с флагом --slots) — состояние слотов, /metrics — метрики Prometheus. У Ollama аналог скромнее: ollama ps.

Какой сервер брать в MAATRIX

Оба на VPS без видеокарты упираются в одно — в пропускную способность памяти, а не в процессор. Конфигурация считается от модели, а не от инструмента.

Честный минимум: 2 vCPU, 8 ГБ RAM, 60 ГБ NVMe. Сюда помещается модель на 7–8B в Q4_K_M (около 5 ГБ весов плюс кэш) с контекстом 4096–8192 и одним слотом. Ограничение называю прямо: 7–13 токенов в секунду, ответ на абзац идёт секунд десять-пятнадцать. Для бота, классификатора, суммаризации по расписанию — нормально, для живого чата — раздражает. Вторую модель рядом не положить: вытеснит первую.

Комфортный вариант: 4–8 vCPU, 16 ГБ RAM, 100 ГБ NVMe. Обработка промпта ускоряется кратно (полка по ядрам есть на генерации, а на промпте — нет), помещаются две модели сразу или одна 9B с контекстом побольше, остаётся место под сборку. Держать оба инструмента параллельно стоит только здесь: на 8 ГБ они выбивают друг друга по памяти.

Что не надо покупать. Гнаться за числом vCPU бессмысленно: 32 потока на 16 ядрах дают падение в двадцать раз, а не прирост — деньги лучше уходят в объём и скорость памяти. А десятки одновременных запросов или ответ быстрее секунды — уже не CPU-сценарий, а сервер с видеокартой; расчёт памяти под разные модели есть в статье Сколько RAM нужно для Ollama.

Локация — Великобритания, Лондон. Причина прикладная: веса с Hugging Face, релизы llama.cpp и реестр Ollama тянутся с зарубежных зеркал, и из Лондона это идёт на полной скорости канала. Для аудитории в Европе задержка минимальна, для российской добавляется 40–60 мс RTT — на фоне 7–13 токенов в секунду это незаметно. Если сервис работает только на Россию и трогает персональные данные, берите российскую локацию: там решает 152-ФЗ, а не скорость.

Оплата — картой российского банка, по СБП, криптовалютой или токеном MAAT; иностранная карта не нужна. Сервер выдаётся с чистой Ubuntu 24.04 или Debian 13. Ollama можно выбрать из каталога apps.maatrix.io и получить готовый сервис сразу, а llama.cpp собрать поверх — командами из третьей секции.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Частые вопросы

Правда, что Ollama — просто обёртка над llama.cpp и работает медленнее?

Раньше была обёрткой, сейчас часть моделей обслуживает её собственный движок поверх ggml. Медленнее она не работает: при одинаковой модели, квантовании и числе потоков разница теряется в погрешности. Замечаемое отставание обычно объясняется умолчаниями — контекстом 4096 и выгрузкой модели через 5 минут простоя.

Можно ли отдать llama.cpp модель, скачанную через Ollama?

Да, и это лучший способ не хранить веса дважды: путь к блобу печатает ollama show --modelfile <модель> | awk '/^FROM/{print $2; exit}', дальше он идёт в -m. Обратное направление хуже: ollama create копирует ваш GGUF в своё хранилище.

Что выбрать, если нужен только OpenAI-совместимый API для одного приложения?

llama.cpp: llama-server даёт /v1/chat/completions, ключ через --api-key и точный контроль над -c, -np и потоками. Ollama тут добавляет лишь удобство обновлений — а один процесс с одной моделью вы обновите и руками.

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.