SSD Nodes Learn 🎉 VPS от $5.50/мес
Руководства Matt ConnorАвтор: Matt Connor

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

Узнайте, как параметры 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, поэтому это замедляет каждый запрос, включая тот единственный, с которого вы начали. Таким образом, увеличение параллелизма может снизить пропускную способность вместо её повышения.

ollama ps

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

Длина контекста и количество слотов перемножаются, поэтому их нужно выбирать совместно. Большой контекст с четырьмя слотами — это четыре больших контекста. Если вы также настраиваете окно контекста 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 загруженной между запросами.

Как выглядят обслуженные, поставленные в очередь и отклоненные запросы со стороны клиента

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

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), так как первый потоковый фрагмент содержит первый токен.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Серверы, рассчитанные на множество одновременных пользователей, работают иначе. Они выделяют KV-кэш небольшими страницами по требованию и добавляют поступающие запросы в уже выполняющийся пакет. Таким образом, потребление памяти следует за реальной нагрузкой, а не за фиксированным разделением. Если ваша цель — обеспечить работу большого количества одновременных пользователей на одном 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-соединение открытым и не передает данные, пока не освободится слот, что со стороны клиента выглядит как медленная работа модели. Признак очереди — характер таймингов: долгая пауза, за которой следует вывод текста с полной скоростью. Если же токены начинают поступать сразу, но медленно — это признак низкой производительности самой модели. Увеличьте количество слотов через systemd drop-in и перезапустите сервис.

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

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

Ускоряет ли 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