llama.cpp на сервере: частые ошибки и решения
llama.cpp собирается из исходников, переименовывает бинарники между релизами и молча делит контекст на слоты — поэтому половина ошибок llama.cpp это не поломка, а расхождение между вашей сборкой и инструкцией, найденной в интернете. Ниже шесть слоёв, на которых всё ломается: сборка, загрузка модели, память, скорость, сервер и железо. С точными строками ошибок и командами проверки.
Содержание
- Сначала выясните, что у вас за сборка и как читать её лог
- Сборка: CURL, «Killed» в компиляторе и Illegal instruction
- Модель не грузится: LFS-заглушка, шарды и unknown architecture
- Память: OOM, арифметика KV-кэша и ловушка `-np`
- «Модель загрузилась, но отвечает по слову в минуту»
- llama-server: порт, API, шаблон чата и systemd
- Какой сервер под llama.cpp брать в MAATRIX
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Сначала выясните, что у вас за сборка и как читать её лог
Первая же команда из старого мануала обычно не работает:
$ ./main -m /opt/models/qwen2.5-7b-instruct-q4_k_m.gguf -p "Привет"
bash: ./main: No such file or directory
Файл модели тут ни при чём. В сентябре 2024 года проект переименовал исполняемые файлы и перенёс их в подкаталог сборки: main стал llama-cli, server — llama-server, quantize — llama-quantize, benchmark — llama-bench. Лежат они в build/bin/, а не в корне репозитория. Любая инструкция с ./main или ./server написана до переименования — остальные её советы, скорее всего, тоже устарели.
Второе — номер сборки:
$ ./build/bin/llama-server --version
version: 6412 (a3f9c1d2)
built with cc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 for x86_64-linux-gnu
Первое число — сквозной номер сборки, тот самый b6412 в тегах на GitHub. Версий вида «1.2.3» у llama.cpp нет: релизов по несколько в день, и разница в пару сотен сборок — это другие имена флагов и другой набор архитектур.
Третье — научитесь читать лог старта. Ключевые строки по порядку: llama_model_loader: loaded meta data with 30 key-value pairs and 292 tensors (файл прочитан), print_info: file format = GGUF V3, load_tensors: CPU model buffer size = 4685.30 MiB (сколько заняли веса), llama_context: n_ctx = 4096 (какое окно вам выдали на самом деле) и в конце main: server is listening on http://127.0.0.1:8080. Последней строки нет — ищите снизу вверх первую строку с error:: всё, что напечатано после неё, уже последствия.
Сборка: CURL, «Killed» в компиляторе и Illegal instruction
Сборки через make в корне репозитория больше нет: Makefile пометили устаревшим, затем удалили. Попытка собрать по старому мануалу даёт:
$ make -j 8
make: *** No targets specified and no makefile found. Stop.
Рабочий путь — только CMake. На чистой Ubuntu 24.04 полный набор такой:
apt update
apt install -y build-essential cmake git libcurl4-openssl-dev
git clone https://github.com/ggml-org/llama.cpp /opt/llama.cpp
cmake -S /opt/llama.cpp -B /opt/llama.cpp/build -DCMAKE_BUILD_TYPE=Release
cmake --build /opt/llama.cpp/build --config Release -j 2
Адрес важен: проект переехал из ggerganov/llama.cpp в ggml-org; старая ссылка редиректится, но в скриптах держите новую.
Пропущенный libcurl. Самая частая ошибка сборки: загрузка моделей с Hugging Face по флагу -hf встроена в common и включена по умолчанию.
-- Could NOT find CURL (missing: CURL_LIBRARY CURL_INCLUDE_DIR)
CMake Error at common/CMakeLists.txt (message):
Could NOT find CURL. Hint: to disable this feature, set -DLLAMA_CURL=OFF
Хинт рабочий, но отключать не надо: без libcurl теряется -hf. На AlmaLinux и Rocky пакет называется libcurl-devel.
Killed внутри компилятора. Выглядит как баг проекта, а на деле это OOM killer:
c++: fatal error: Killed signal terminated program cc1plus
compilation terminated.
make[2]: *** [ggml/src/CMakeFiles/ggml-cpu.dir/build.make:90: ...ggml-cpu.cpp.o] Error 1
Каждый процесс g++ на тяжёлых файлах ggml съедает полтора-два гигабайта, а -j $(nproc) запускает их по числу ядер: на VPS с 2 ГБ четыре компилятора не помещаются. Подтверждение — dmesg -T | grep -i 'out of memory'. Лечится -j 2 или временным swap-файлом:
fallocate -l 4G /swapfile && chmod 600 /swapfile
mkswap /swapfile && swapon /swapfile
Swap для сборки нормален, под саму модель — вреден, об этом ниже. После сборки снимите: swapoff /swapfile.
Старый дистрибутив. На Ubuntu 20.04 в репозиториях лежат CMake 3.16 и GCC 9 — современный llama.cpp на них не собирается. Берите Ubuntu 24.04 (CMake 3.28, GCC 13) или Debian 12 (CMake 3.25, GCC 12).
Illegal instruction (core dumped). Собралось, а при запуске процесс падает без единой строки объяснения. Опция GGML_NATIVE включена по умолчанию и добавляет -march=native: бинарник получает инструкции того процессора, на котором компилировался, и переезд на узел с другим CPU даёт падение на первой же AVX-512-инструкции. Что поддерживает машина:
lscpu | grep -o -E 'avx512[a-z0-9_]*|avx2|f16c|fma' | sort -u
Переносимая сборка задаётся явно: -DGGML_NATIVE=OFF -DGGML_AVX2=ON -DGGML_FMA=ON -DGGML_F16C=ON — на несколько процентов медленнее, зато переживает переезд.
libllama.so: cannot open shared object file. Библиотеки собираются динамическими, и в build/bin рядом с llama-server лежат libllama.so, libggml.so, libggml-base.so и libggml-cpu.so. Копируете один бинарник в /usr/local/bin — получаете:
/usr/local/bin/llama-server: error while loading shared libraries: libllama.so:
cannot open shared object file: No such file or directory
Три выхода: статическая сборка (-DBUILD_SHARED_LIBS=OFF), копирование каталога build/bin целиком либо echo /opt/llama.cpp/build/bin > /etc/ld.so.conf.d/llama.conf && ldconfig. Нюанс новых сборок: бэкенды ggml подгружаются динамически, и libggml-cpu*.so обязана лежать рядом с бинарником — без неё считать нечем.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверМодель не грузится: LFS-заглушка, шарды и unknown architecture
Прежде чем разбирать флаги, проверьте сам файл. GGUF начинается с четырёх байт GGUF:
ls -lh /opt/models/model.gguf
head -c 4 /opt/models/model.gguf | xxd
# 00000000: 4747 5546 GGUF
Заглушка Git LFS. Если вместо магии видно текст version https://git-lfs.github.com/spec/v1, а размер файла 130 байт вместо пяти гигабайт, репозиторий клонировали без git-lfs и скачали указатель. Ошибка при этом невнятная: llama_model_load: error loading model: llama_model_loader: failed to load model from /opt/models/model.gguf. Лечится apt install git-lfs && git lfs pull.
Оборванная загрузка. Файл нужного вида, но не докачан. Диагноз однозначный:
llama_model_loader: tensor 'blk.27.ffn_down.weight' data is not within the file bounds,
model is corrupted or incomplete
Не чините — качайте заново с curl -C - или wget -c и сверяйте размер.
Шарды. Модели крупнее примерно 48 ГБ выкладывают частями: Qwen2.5-72B-Instruct-Q4_K_M-00001-of-00002.gguf и так далее. В -m передают первый шард — остальные llama.cpp найдёт сам по шаблону имени, если файлы в одном каталоге. Скормите второй — получите жалобы на отсутствующие тензоры. Склеить:
./build/bin/llama-gguf-split --merge Qwen2.5-72B-Q4_K_M-00001-of-00002.gguf Qwen2.5-72B.gguf
Неизвестная архитектура. Классика при свежей модели и старой сборке:
llama_model_load: error loading model: error loading model architecture:
unknown model architecture: 'qwen3moe'
llama_model_load_from_file_impl: failed to load model
Файл не битый: поддержка каждой архитектуры добавляется отдельным патчем, и GGUF, выложенный вчера, требует сборки не старше вчерашней. Лечение — git pull и пересборка, минут десять на четырёх ядрах. Зеркальный случай — модель 2023 года в .bin или GGML v3 на свежей сборке: ругань будет на unknown (magic, version) combination. Старые форматы выброшены.
Скачивание прямо из llama.cpp. Если CURL на месте, модель можно не искать руками:
./build/bin/llama-server -hf bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M --port 8080
Файл ложится в ~/.cache/llama.cpp. Отказ common_download_file: curl_easy_perform() failed почти всегда означает не проблему llama.cpp, а недоступность Hugging Face с адреса сервера — типовая история для российских IP.
Память: OOM, арифметика KV-кэша и ловушка `-np`
Веса — только половина расхода. Модель на 7–8 млрд параметров в Q4_K_M занимает около пяти гигабайтов: на нашем стенде qwen2.5:7b держит в памяти 5,1 ГБ, mistral:7b — 5,0 ГБ, llama3.1:8b — 5,6 ГБ, qwen2.5:3b — 2,2 ГБ. Вторая половина — KV-кэш: 2 × n_layer × n_kv_head × head_dim × байт_на_значение на каждый токен окна. Для Llama 3.1 8B это 2 × 32 × 8 × 128 × 2 = 131 072 байта, ровно 128 КБ на токен.
Окно -c | KV-кэш (f16) | Итого с весами 5 ГБ |
|---|---|---|
| 4 096 | 0,5 ГБ | ~5,5 ГБ |
| 8 192 | 1,0 ГБ | ~6 ГБ |
| 32 768 | 4,0 ГБ | ~9 ГБ |
| 131 072 | 16,0 ГБ | ~21 ГБ |
Отсюда главный совет: никогда не ставьте -c 0. Ноль означает «взять окно, на котором модель обучалась», у современных моделей это 131 072 токена — и сервер честно попытается выделить разом шестнадцать гигабайтов. По умолчанию llama-server берёт 4096.
Нехватка памяти проявляется тремя способами. Если аллокатор успел отработать штатно:
ggml_backend_cpu_buffer_type_alloc_buffer: failed to allocate buffer of size 17179869184
llama_kv_cache_init: failed to allocate buffer for kv cache
llama_new_context_with_model: failed to create context with model '/opt/models/model.gguf'
Если не успел — процесс исчезает без единой строки в своём логе, и искать надо в ядре:
$ dmesg -T | grep -i 'killed process'
[Fri Aug 28 11:42:07 2026] Out of memory: Killed process 1874 (llama-server)
total-vm:12034512kB, anon-rss:7812340kB, UID:1001
Третий способ самый коварный: памяти хватило за счёт mmap, и всё «работает», просто очень медленно — об этом следующий раздел.
Ловушка -np. Флаг -c задаёт общий контекст, который делится между слотами. Запуск llama-server -c 8192 -np 4 выдаёт каждому клиенту вчетверо меньше, и это видно в логе старта:
slot init: id 0 | task -1 | new slot n_ctx_slot = 2048
Дальше пользователь присылает промпт на три тысячи токенов и получает HTTP 400:
{"error":{"code":400,"message":"the request exceeds the available context size, try increasing the context size or enable context shift","type":"exceed_context_size_error"}}
Правило: -c = нужное окно на клиента × число слотов. Хотите 8k на четверых — ставьте -c 32768 и держите под это 4 ГБ кэша.
Как сэкономить. Квантование кэша --cache-type-k q8_0 --cache-type-v q8_0 уменьшает его примерно вдвое. Две оговорки: квантованный V-кэш требует flash attention (-fa on в новых сборках, просто -fa в старых), а уровень q4_0 заметно портит длинный контекст.
--mlock. Прибивает веса к памяти и запрещает вытеснение. Требует лимита: без него в логе будет warning: failed to mlock 4096-byte buffer ... Cannot allocate memory и подсказка Try increasing RLIMIT_MEMLOCK. В юните systemd это строка LimitMEMLOCK=infinity.
«Модель загрузилась, но отвечает по слову в минуту»
Отдельный класс жалоб, и виноват в нём чаще всего не процессор.
mmap. По умолчанию llama.cpp не читает GGUF в память, а отображает его: процесс стартует мгновенно, RSS в top скромный — веса живут страницами в файловом кэше. Пока памяти больше, чем весит модель, это лучший режим; как только меньше — каждый токен обходит весь файл, и страницы читаются с диска по кругу. Признаки: процесс подолгу в состоянии D, в vmstat 1 колонка wa за пятьдесят, а bi в десятках тысяч блоков в секунду.
Диагностика — запуск с --no-mmap: модель читается в память целиком на старте и либо честно загружается, либо её убивает OOM killer на первых секундах. Быстрый понятный отказ вместо медленной загадочной работы; на сервере --no-mmap стоит держать постоянно.
Swap. Если модель не помещается, а swap включён, вместо чистого отказа вы получите перемалывание диска. Крутить vm.swappiness бесполезно: под LLM своп — не запас, а тормоз.
Потоки: -t против -tb. -t — потоки генерации, -tb — потоки обработки промпта, и путать их дорого: генерация упирается в пропускную способность памяти, обработка промпта — в арифметику процессора.
Замер на нашем стенде: 16 vCPU (8 физических ядер AMD EPYC 9554 плюс гипертреды, DDR5), qwen2.5:7b в Q4_K_M, контекст 4096, движок llama.cpp в составе Ollama 0.33.1. Три прогона, в таблице медиана; промпт мерился холодным, без кэша префикса:
| Потоков | Генерация, ток/с | Обработка промпта, ток/с |
|---|---|---|
| 2 | 5,7 | 12,6 |
| 4 | 7,6 | 31,0 |
| 8 | 7,6 | 61,7 |
| 16 | 7,4 | 68,0 |
| 32 | 0,35 | 10,9 |
Генерация выходит на полку уже на четырёх потоках: дальше упор в память, и ни восемь, ни шестнадцать ничего не добавляют. Обработка промпта, наоборот, растёт до восьми потоков впятеро. Вывод для этой машины — -t 4 -tb 8: генерация ничего не теряет, а длинные промпты идут вдвое быстрее, чем при -t 4 -tb 4.
Последняя строка отдельно: 32 потока на 16 vCPU дают обвал в двадцать раз — это неработоспособность. Внутри ggml каждый слой заканчивается барьером синхронизации, и фронт ждёт самый медленный поток; когда потоков вдвое больше, чем ядер, они вытесняют друг друга. Не задавайте -t больше числа доступных ядер.
Другие модели на том же стенде при 16 потоках: llama3.1:8b — 12,8 ток/с, mistral:7b — 12,1, gemma2:9b — 8,8, qwen2.5:3b — 34,1. «7B на CPU» — это не цифра, а диапазон.
llama-server: порт, API, шаблон чата и systemd
Типовой запуск со всеми обсуждавшимися флагами:
/opt/llama.cpp/build/bin/llama-server \
-m /opt/models/qwen2.5-7b-instruct-q4_k_m.gguf \
--host 127.0.0.1 --port 8080 \
-c 16384 -np 2 -t 4 -tb 8 --no-mmap \
--api-key "$LLAMA_API_KEY" --alias qwen2.5-7b
Про безопасность прямо. По умолчанию llama-server слушает 127.0.0.1:8080 и не требует никакой авторизации. Человек, у которого сервер не отвечает снаружи, меняет хост на 0.0.0.0 — и получает открытый эндпоинт генерации, который находят сканерами за часы. Правильно: оставить 127.0.0.1, наружу выпускать через Nginx с TLS, задать --api-key, порт закрыть — ufw allow 22/tcp, ufw deny 8080/tcp. Не поднимается — смотрите ss -tlnp | grep 8080: чаще всего порт занят предыдущим экземпляром.
API — не такой, как у Ollama. Вторая по частоте причина жалоб «клиент не видит модель». llama-server отдаёт нативный /completion, служебные /health, /props, /slots и OpenAI-совместимый набор: /v1/chat/completions, /v1/models, /v1/embeddings. Эндпоинтов /api/chat и /api/tags у него нет — это API Ollama, и клиент, настроенный на «Ollama URL», получит честный 404. Меняя Ollama на llama.cpp под тем же веб-интерфейсом, указывайте OpenAI-совместимый адрес http://127.0.0.1:8080/v1 и ключ из --api-key.
Проверка живости и реально применившихся параметров:
curl -s http://127.0.0.1:8080/health
# {"status":"ok"}
curl -s http://127.0.0.1:8080/props | jq '.default_generation_settings.n_ctx, .model_path'
Деталь для мониторинга: пока модель грузится, /health отвечает кодом 503 и телом {"error":{"code":503,"message":"Loading model","type":"unavailable_error"}}. Сторожевой скрипт, перезапускающий сервис по любому не-200, будет убивать сервер на сороковой секунде загрузки. Считайте 503 нормой в первую минуту.
Шаблон чата. llama.cpp берёт Jinja-шаблон из метаданных GGUF. Нет его или написан экзотично — сервер откатывается на ChatML, и модель игнорирует системный промпт или дописывает реплики за пользователя. Что применилось, видно в curl -s http://127.0.0.1:8080/props | jq -r .chat_template. Флаг --jinja включает полноценный движок шаблонов и нужен для вызова инструментов, --chat-template-file задаёт шаблон принудительно.
Юнит systemd, в котором учтены грабли из второго и четвёртого разделов:
[Unit]
Description=llama.cpp server
After=network-online.target
[Service]
User=llama
WorkingDirectory=/opt/llama.cpp
Environment=LD_LIBRARY_PATH=/opt/llama.cpp/build/bin
EnvironmentFile=/etc/llama/llama.env
ExecStart=/opt/llama.cpp/build/bin/llama-server -m /opt/models/qwen2.5-7b-instruct-q4_k_m.gguf --host 127.0.0.1 --port 8080 -c 16384 -np 2 -t 4 -tb 8 --no-mmap
Restart=on-failure
RestartSec=15
LimitMEMLOCK=infinity
[Install]
WantedBy=multi-user.target
LD_LIBRARY_PATH здесь — способ не собирать статически и не ловить libllama.so. RestartSec=15 не косметика: без паузы сервер, убитый по OOM на этапе загрузки, будет перезапускаться в цикле и молотить диск. В Nginx обязательны proxy_buffering off; и proxy_read_timeout 600s; — иначе потоковая выдача приедет одним куском в конце или оборвётся на середине.
Какой сервер под llama.cpp брать в MAATRIX
Сразу честно: llama.cpp в каталоге apps.maatrix.io нет — это исходный проект, который каждый собирает под свои флаги. Сервер приходит чистым, с Ubuntu 24.04 или Debian 12, и вы ставите его по второму разделу статьи, минут за пятнадцать. Нужна готовая сборка — в каталоге лежат родственные сервисы: Ollama (тот же движок llama.cpp внутри), AnythingLLM, LiteLLM, Dify, Qdrant. Они ставятся автоматически при заказе, доступы появляются в кабинете.
Честный минимум: 4 физических ядра с AVX2, 8 ГБ RAM, 40 ГБ NVMe. Помещается 7–8B в Q4_K_M: около 5 ГБ весов, 2 ГБ на контекст 16k, остальное системе, обязательно с --no-mmap. Ограничения прямо: вторую модель рядом не поднять, окно 32k не влезет, а скорость генерации будет однозначной — на нашем стенде qwen2.5:7b давала 7,6 токена в секунду.
Комфортный вариант: 8 физических ядер, 16–32 ГБ RAM, 80–160 ГБ NVMe. Свободно идёт 14B в Q4, либо 8B с окном 32k и четырьмя слотами, либо модель плюс веб-интерфейс и векторная база рядом. Про диск не забывайте: один файл 70B в Q4 — это 40+ ГБ.
Чего покупать не надо — количество vCPU: по таблице из пятого раздела шестнадцать потоков не быстрее восьми, а тридцать два медленнее в двадцать раз. Деньги вложите в объём и скорость памяти — она определяет, какая модель поместится.
Локация — Великобритания, Лондон. Локальный инференс выбирают ради того, чтобы переписка, документы и код не уходили в чужое облако, — лондонская площадка держит их в европейском правовом периметре, рядом с GDPR. До ЕС 10–25 мс, до Москвы 45–60 мс: при генерации в единицы токенов в секунду пинг не узкое место. Практическая выгода в другом — с британского адреса Hugging Face и GitHub открываются без ухищрений, и пятигигабайтный GGUF не обрывается на середине. Если аудитория целиком российская и есть требования 152-ФЗ — берите RU-локацию. Оплата — картами российских банков, по СБП, криптовалютой или токеном MAAT.
И честный потолок. Всё описанное — про CPU. Нужно больше 20–30 токенов в секунду или десяток одновременных пользователей — потоками не лечится: нужен GPU с VRAM не меньше размера модели и сборка с -DGGML_CUDA=ON, только тогда появляется смысл у -ngl 99. На CPU-сборке -ngl не выдаёт ошибку, а молча игнорируется: «поставил -ngl 99, а быстрее не стало» почти всегда означает сборку без CUDA — в логе тогда только CPU model buffer size.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
./main -m model.gguf пишет No such file or directory, хотя файл модели на месте.
Не хватает не модели, а бинарника: main переименован в llama-cli, server — в llama-server, и лежат они в build/bin/. Запускайте ./build/bin/llama-cli -m model.gguf -p "...". Инструкции старше сентября 2024 года используют старые имена, так что остальные их команды тоже стоит перепроверить.
Сборка падает на c++: fatal error: Killed signal terminated program cc1plus. Это баг llama.cpp?
Нет, это OOM killer. Каждый процесс g++ на файлах ggml берёт полтора-два гигабайта, а -j $(nproc) запускает их по числу ядер. Собирайте с -j 2 либо добавьте временный swap на 4 ГБ и снимите его после сборки. Подтверждение — dmesg -T | grep -i 'out of memory'.
Поставил -c 131072, как заявлено у модели, и сервер не стартует.
Окно оплачивается KV-кэшем: у Llama 3.1 8B это 128 КБ на токен, то есть 16 ГБ на 128k сверх 5 ГБ весов. Ставьте реальное нужное окно, при нехватке добавьте --cache-type-k q8_0 --cache-type-v q8_0 вместе с -fa on. И помните, что -c делится между слотами: с -np 4 каждому клиенту достанется четверть.
Нужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.