SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-22

Настройка параллелизма в Ollama: OLLAMA_NUM_PARALLEL

Узнайте, как параметры OLLAMA_NUM_PARALLEL и OLLAMA_MAX_QUEUE управляют очередью запросов. Разберитесь, почему каждый новый слот потребляет VRAM и вызывает ошибку 503.

Что происходит со вторым запросом к Ollama во время генерации первого

Параллелизм Ollama определяется тремя переменными окружения, и по умолчанию одна загруженная модель обрабатывает только один запрос за раз. Второй запрос не отклоняется, и он не получает частичный ответ. Он ожидает в очереди, пока не освободится слот, после чего выполняется с обычной скоростью.

Входящий запрос может ожидать три варианта развития событий. Он запускается немедленно, если есть свободный слот. Он ожидает в очереди. Либо очередь уже заполнена, и сервер отклоняет запрос с ошибкой HTTP 503. Какой из вариантов будет применен, зависит от OLLAMA_NUM_PARALLEL, OLLAMA_MAX_QUEUE и OLLAMA_MAX_LOADED_MODELS.

Настройки по умолчанию безопасны, именно поэтому второй пользователь может сообщать, что сервер «завис», хотя на самом деле всё работает исправно. Добавление слотов требует изменения всего двух строк. Сложность заключается в памяти. Для каждого параллельного слота требуется собственный кэш ключей и значений (KV cache) — блок памяти, в котором модель хранит уже обработанные токены. Если добавить слоты без увеличения объема VRAM (видеопамяти на GPU), медленный ответ превратится в ошибку загрузки модели.

За что отвечают параметры OLLAMA_NUM_PARALLEL, OLLAMA_MAX_QUEUE и OLLAMA_MAX_LOADED_MODELS

Это значения по умолчанию в текущих релизах Ollama на август 2026 года. Вместо того чтобы полагаться на эти цифры, проверьте свои настройки с помощью строки лога, приведенной ниже.

  • OLLAMA_NUM_PARALLEL определяет, сколько запросов одна загруженная модель обрабатывает одновременно. Значение по умолчанию — 1, поэтому запросы обслуживаются последовательно.
  • OLLAMA_MAX_LOADED_MODELS определяет, сколько различных моделей могут находиться в памяти одновременно. Значение по умолчанию — 0, что означает автоматический выбор Ollama: три модели на GPU и три на машине без GPU.
  • OLLAMA_MAX_QUEUE определяет, сколько запросов могут находиться в очереди ожидания. Значение по умолчанию — 512. Запрос, поступивший при заполненной очереди, немедленно отклоняется.

Максимальный объем потребляемой памяти в худшем случае равен произведению первых двух параметров. Две загруженные модели по четыре слота каждая означают восемь выделенных слотов KV-кэша, находящихся в памяти одновременно, и Ollama попытается обеспечить их работу. На сервере с одним GPU обычно лучше держать одну модель и выделять ей слоты, так как расчеты остаются простыми и понятными.

Почему каждый параллельный слот требует VRAM

Когда Ollama загружает модель, она запускает отдельный процесс-исполнитель (runner). Здесь важны два аргумента: -c — это общий контекст, для которого исполнитель выделяет KV-кэш, и -np — количество параллельных последовательностей. Ollama устанавливает -c как произведение длины контекста на один запрос и количества слотов. Затем исполнитель равномерно распределяет этот объем между слотами, чтобы каждый запрос получал запрошенную вами длину контекста.

Это и есть основное ограничение, из-за которого параллелизм не является бесплатным. Переход от одного слота к четырем требует в четыре раза больше KV-кэша при той же длине контекста на запрос. Между слотами ничего не разделяется, и доля простаивающего слота не передается занятому, так как разделение фиксируется при запуске исполнителя.

Вы можете увидеть реальные значения вместо тех, которые планировали установить:

journalctl -u ollama --no-pager -n 500 | grep "starting llama-server"

Эта строка содержит полную командную строку исполнителя, включая -c и -np. Если после установки переменной -np равно 1, значит, настройка не применяется к серверу; причины этого рассматриваются в следующем разделе.

Если веса модели вместе с KV-кэшем не помещаются в VRAM, Ollama перемещает часть слоев в системную RAM, и эти слои выполняются на CPU. Слои на CPU работают значительно медленнее, чем на GPU, поэтому это замедляет каждый запрос, включая тот единственный, с которого вы начали. Таким образом, увеличение параллелизма может снизить пропускную способность вместо её повышения. При использовании достаточно большой модели веса сами по себе определяют ситуацию еще до начала расчетов для слотов, поэтому самостоятельный запуск модели размером с Kimi K3 — это вопрос количества имеющихся у вас видеокарт, а не количества настроенных слотов.

ollama ps

Столбец PROCESSOR показывает 100% GPU, когда всё помещается в память. Значение вроде 35%/65% CPU/GPU означает, что часть модели выполняется на CPU. Столбец SIZE включает KV-кэш, поэтому он увеличивается при повышении количества слотов и перезагрузке модели. Увеличьте OLLAMA_NUM_PARALLEL, перезапустите, отправьте один запрос и снова выполните ollama ps: это и есть стоимость вашего изменения в памяти, измеренная, а не предполагаемая. Если это измерение показывает, что модель больше не помещается, помните, что веса — это вторая половина того же бюджета, и переход с fp16 на сборку q8 или q4 часто освобождает больше VRAM, чем стоит слот, который вы пытались добавить.

Длина контекста и количество слотов перемножаются, поэтому их нужно выбирать совместно. Большой контекст с четырьмя слотами — это четыре больших контекста. Если вы также настраиваете окно контекста num_ctx для вашей модели, изменяйте только один из этих параметров за раз, иначе вы не поймете, что именно переполнило видеокарту.

Как сохранить эти переменные после перезагрузки

В Linux Ollama работает как systemd-сервис. Выполнение export OLLAMA_NUM_PARALLEL=4 в вашей оболочке ничего не меняет, так как systemd запускает сервис в собственном окружении и не видит вашу оболочку. Используйте drop-in файл.

sudo systemctl edit ollama.service

Добавьте следующее в открывшемся редакторе:

[Service]
Environment="OLLAMA_NUM_PARALLEL=4"
Environment="OLLAMA_MAX_LOADED_MODELS=1"
Environment="OLLAMA_MAX_QUEUE=32"

Затем выполните перезагрузку конфигурации и перезапуск:

sudo systemctl daemon-reload
sudo systemctl restart ollama
systemctl show ollama --property=Environment

systemctl show выводит переменные, которые systemd передаст процессу. Если вашей переменной там нет, значит, drop-in файл не был сохранён или вы пропустили daemon-reload. Проверьте это также со стороны самого сервера:

journalctl -u ollama --no-pager | grep "server config" | tail -1

Ollama записывает всё своё окружение в лог при запуске в строке с сообщением server config. Эта карта — истина в последней инстанции. Это самый быстрый способ разрешить спор о том, вступила ли переменная в силу.

Уже загруженная модель сохраняет количество слотов, с которыми она была запущена, так как это значение фиксируется в процессе выполнения при старте. Указанный выше перезапуск выгружает всё из памяти, поэтому следующий запрос загрузит модель с новыми настройками и потребует времени на загрузку один раз. Время удержания модели в памяти после этого регулируется отдельно, что описано в поддержании модели Ollama в памяти между запросами.

Как выглядят состояния served, queued и refused со стороны клиента

Отправьте несколько запросов одновременно и замерьте время их выполнения. Следующая команда запускает восемь потоковых запросов параллельно и выводит статус и время для каждого из них:

for i in $(seq 1 8); do
  curl -s -o /dev/null \
    -w "req$i http=%{http_code} ttfb=%{time_starttransfer}s total=%{time_total}s\n" \
    http://127.0.0.1:11434/api/generate \
    -d '{"model":"llama3.2:3b","prompt":"Explain what a KV cache is.","stream":true}' &
done
wait

ttfb — это время до получения первого байта потока, которое близко к времени до первого токена (TTFT), так как первый потоковый фрагмент содержит первый токен.

Served (обработано) параллельно. Каждый запрос показывает схожее значение ttfb, а total увеличивается для всех них одновременно. GPU распределяется между активными слотами, поэтому каждый ответ генерируется медленнее, чем при одиночном запросе, но общее количество ответов в минуту возрастает. Именно этот режим вы получаете при увеличении OLLAMA_NUM_PARALLEL.

Queued (в очереди). Первые запросы отвечают быстро, а последующие показывают большое значение ttfb, за которым следует нормальная генерация. Ожидание вызвано очередью, а не моделью. Пользователь, наблюдающий за окном чата, видит долгую паузу, после которой текст появляется с полной скоростью. Такая форма — медленный старт и последующая высокая скорость — является признаком очереди, а не перегруженного GPU.

Refused (отказано). Клиент почти мгновенно получает http=503, а тело ответа выглядит так:

{"error":"server busy, please try again.  maximum pending requests exceeded"}

Это сообщение означает, что очередь была заполнена в момент поступления запроса. Оно не содержит информации о VRAM или состоянии модели.

Важное ограничение: Ollama не публикует глубину очереди. ollama ps и эндпоинт /api/ps сообщают о загруженных моделях, а не о запросах, ожидающих обработки. Поэтому измеряйте очередь со стороны клиента, отслеживая время до первого байта, либо подсчитывайте количество ответов 503 на уровне прокси-сервера, стоящего перед Ollama.

Почему меньшее значение MAX_QUEUE часто является более предпочтительным

Очередь размером 512 кажется большой, но для одного слота она практически бесполезна. Запрос 300 будет ждать завершения 299 предыдущих генераций. В лучшем случае это займет минуты. Любой HTTP-клиент сдастся гораздо раньше, поэтому вызывающая сторона получит таймаут на стороне клиента. Это не даст никакой информации о причине, а ваша система мониторинга не получит данных для оповещения.

Установите размер очереди примерно равным тому количеству запросов, которое сервер успевает обработать до истечения таймаута клиента. Тогда переполнение очереди будет немедленно приводить к ошибке 503. Ошибка 503 полезна: reverse proxy может повторить запрос, клиент может применить стратегию backoff, дашборд может учесть это событие, а администратор — увидеть его. Рассчитайте это число на основе собственных измерений. Если генерация занимает около 10 секунд, а клиент ожидает 60, то в это окно уложится около 6 запросов на слот. Очередь, значительно превышающая это значение, приведет лишь к таймаутам.

Когда стоит использовать очередь перед Ollama

Встроенная очередь работает по принципу «первым пришел — первым обслужен» (FIFO) и не учитывает, кто именно отправляет запрос. Если одно приложение взаимодействует с одним сервером, этого достаточно, а добавление инфраструктуры лишь создаст дополнительные точки отказа. Используйте внешнюю очередь, если выполняется одно из следующих условий:

  • Вам нужен приоритет. Интерактивный чат не должен ожидать завершения пакетной задачи по суммаризации. В очереди Ollama нет приоритетов, поэтому пакетные задачи должны удерживаться снаружи и подаваться постепенно.
  • Вам нужна справедливость. Один клиент может полностью занять очередь, из-за чего все остальные получат ошибку 503.
  • Вам нужно, чтобы задачи сохранялись после перезагрузки. Очередь находится в оперативной памяти сервера. Если перезапустить Ollama, все ожидающие запросы будут потеряны.
  • Вам нужны полноценные повторные попытки с экспоненциальной задержкой (backoff), которые записываются в место, доступное для последующего анализа.

Легкий вариант — использование reverse proxy. В nginx директива limit_conn ограничивает количество одновременных соединений, а limit_req ограничивает скорость поступления запросов от одного клиента, поэтому избыточный трафик отклоняется на уровне прокси и не попадает в очередь Ollama. Тяжелый вариант — это очередь задач с базой данных перед воркером, который вызывает Ollama; это необходимо, если запросы должны пережить перезапуск процесса. Расчет такой системы для реальной нагрузки — отдельная задача: в планировании self-hosted LLM для одновременных пользователей приведены необходимые вычисления, а в запуске Ollama на VPS описана базовая установка, на которую опираются эти переменные.

Когда правильным решением является другой сервер

Существует предел, который невозможно преодолеть настройками. При загрузке модели Ollama разделяет KV-кэш на равные фиксированные слоты. Память простаивающего слота нельзя использовать для активного, а количество слотов нельзя изменить без выгрузки модели. Такая архитектура подходит для одного пользователя, небольшой команды или агента для написания кода.

Серверы, рассчитанные на множество одновременных пользователей, работают иначе. Они выделяют KV-кэш небольшими страницами по требованию и добавляют поступающие запросы в уже выполняющийся пакет (batch), поэтому потребление памяти соответствует реальной нагрузке, а не фиксированному разделению. Если ваша цель — обеспечить большое количество одновременных пользователей на одном GPU, это архитектурное различие важнее любого значения OLLAMA_NUM_PARALLEL. Сравнение Ollama и vLLM поможет вам сделать выбор. Однако не стоит переходить на другое решение только из принципа: обслуживание дополнительного сервера требует усилий, и если ваш трафик ограничен несколькими пользователями, встроенное поведение является оптимальным.

Измерение собственной пропускной способности и времени до первого токена

Показатели количества токенов в секунду, опубликованные другими, зависят от чужих GPU, модели, квантования, длины контекста и промпта. Ни один из этих параметров не совпадает с вашими, поэтому воспринимайте любые цифры лишь как приблизительный ориентир и проводите измерения на своей машине.

Ollama возвращает временные показатели в финальном JSON-объекте каждого ответа. eval_count — это количество сгенерированных токенов, а eval_duration — время, затраченное на их генерацию, в наносекундах.

sudo apt install -y jq
curl -s http://127.0.0.1:11434/api/generate \
  -d '{"model":"llama3.2:3b","prompt":"Explain what a KV cache is.","stream":false}' \
  | jq '{prompt_eval_count, eval_count, eval_duration, tokens_per_second: (.eval_count / (.eval_duration / 1000000000))}'

Запустите это с одним слотом, затем повторите при той степени параллелизма, которую вы ожидаете, и сравните два показателя, определяющих удовлетворенность пользователей: время до первого токена и количество токенов в секунду на запрос. Пропускная способность на запрос всегда снижается при добавлении слотов. Вопрос лишь в том, падает ли она сильнее, чем готовы принять ваши пользователи. В статье Измерение количества токенов в секунду в локальной LLM метод описан более подробно, включая способы сохранения постоянства промпта между запусками.

Публичная точка входа с большой очередью — цель для атак типа «отказ в обслуживании»

Настройка OLLAMA_HOST=0.0.0.0:11434 делает API доступным на всех сетевых интерфейсах, а в Ollama нет встроенной аутентификации. Открытая точка входа с очередью по умолчанию примет 512 ожидающих запросов от любого, кто её обнаружит. Заполнение этой очереди практически ничего не стоит злоумышленнику: длинные промпты, отсутствие авторизации, ограничений по частоте запросов и оплаты. В результате ваши пользователи получают ответы 503 или вынуждены долго ждать, а сервер постоянно занят обработкой.

Оставьте прослушивание только на loopback и обращайтесь к нему через SSH-туннель или частную сеть, либо установите перед ним прокси с аутентификацией и ограничением частоты запросов. В обеспечении безопасности API-точки входа Ollama рассматриваются оба варианта. Настраивайте очередь только после этого, так как размер очереди — это параметр производительности, а не средство защиты.

FAQ

Почему мой второй запрос к Ollama ожидает завершения первого?

Потому что OLLAMA_NUM_PARALLEL по умолчанию равен 1, поэтому загруженная модель обрабатывает запросы по очереди, а остальные ожидают в порядке очереди. Ожидающий запрос удерживает HTTP-соединение открытым и не передает данные, пока не освободится слот, что со стороны клиента выглядит как медленная работа модели. Признак очереди — это характер задержки: долгая пауза, за которой следует вывод текста на полной скорости. Если же текст поступает медленно с самого первого токена, значит, модель работает медленно. Увеличьте количество слотов через drop-in файл systemd и перезапустите сервис.

Что означает ошибка "server busy, please try again. maximum pending requests exceeded"?

Это ошибка переполнения очереди Ollama, возвращаемая с HTTP-статусом 503. Количество ожидающих запросов достигло OLLAMA_MAX_QUEUE (по умолчанию 512), поэтому новый запрос был отклонен, а не добавлен в очередь. Это не ошибка памяти и не ошибка модели. Увеличение размера очереди лишь заставит клиентов дольше ждать перед тем же отказом. Реальные способы решения: увеличить количество слотов, если позволяет VRAM, снизить входящую нагрузку или использовать прокси-очередь перед Ollama, которая умеет повторять запросы и управлять приоритетами.

Ускоряет ли Ollama увеличение OLLAMA_NUM_PARALLEL?

Нет. Это позволяет обрабатывать больше запросов одновременно, но каждый из них будет медленнее, чем при выполнении в одиночку, так как они делят ресурсы одного GPU. Это также увеличивает потребление KV-кэша, поскольку Ollama запускает процесс обработки с общим контекстом, равным произведению длины контекста на количество слотов. Если результат перестает помещаться в VRAM, Ollama вытесняет слои на CPU, и каждый запрос замедляется, даже если он выполняется один. Проверьте ollama ps после внесения изменений и убедитесь, что в столбце PROCESSOR по-прежнему указано 100% GPU.

Нужно ли перезапускать Ollama после изменения этих переменных?

Да. Сервер считывает их при запуске, а работающая модель сохраняет количество слотов, зафиксированное в процессе выполнения при старте. Отредактируйте drop-in файл с помощью sudo systemctl edit ollama.service, затем выполните sudo systemctl daemon-reload и sudo systemctl restart ollama. Проверьте результат командой systemctl show ollama --property=Environment, а затем посмотрите строку server config в journalctl -u ollama, где указаны переменные окружения, с которыми фактически был запущен сервер.

Сколько параллельных слотов следует установить?

Начните с 1 и увеличивайте значение пошагово. После каждого шага перезапускайте Ollama, отправляйте один запрос для загрузки модели и выполняйте ollama ps. Остановитесь на последнем значении, при котором PROCESSOR всё ещё показывает 100% GPU, а столбец SIZE оставляет запас памяти для самого длинного контекста, который вы планируете использовать. Затем измерьте время до первого токена и скорость генерации токенов в секунду при реальной нагрузке. Если скорость обработки одного запроса упала ниже допустимого для ваших пользователей уровня, вернитесь на один шаг назад.

#ollama#concurrency#vram#queueing#self-hosted-llm