Ollama или vLLM для конкурентного инференса: выбор сервера по нагрузке
Сравнение Ollama и vLLM по конкурентности, throughput, latency, очередям, batching и нагрузке на GPU
Ollama или vLLM для конкурентного инференса нужно выбирать по нагрузке и затратам на поддержку. Ollama против vLLM по конкурентности нельзя просто оценить одним запуском, ведь результат зависит от модели, формата весов, оборудования и длины контекста. Личному чату важен простой жизненный цикл модели, а серверному API – batching и загрузка ускорителя.
При какой конкурентности vLLM начинает выигрывать у Ollama?
Общего порога нет: vLLM начинает выигрывать, когда очередь запросов даёт планировщику собирать полезные пакеты, а ускоритель ещё не упёрся в память. Практический порог показывает sweep-тест на своей модели, контексте и SLO. При одном клиенте или CPU-инференсе преимущество может не проявиться вовсе.
Начать с конкуренции, контекста и цели сервиса
Поток запросов у трёх типичных сервисов выглядит по-разному. Личный чат ведёт один активный диалог и допускает паузу при загрузке модели. Внутренний API получает всплески от сотрудников. Многопользовательскому batch-сервису приходится выдерживать очередь и соблюдать пределы TTFT и полной задержки.
Для каждого случая нужны длины входа и ответа, доля потоковых запросов, всплеск, средняя и пиковая конкурентность. Эти данные влияют на выбор ускорителя: длинный контекст расходует KV-cache, долгая генерация удерживает слот, а средняя конкурентность не покажет момент, когда длинные диалоги сойдутся и поднимут p99.
Сравнение Ollama и vLLM требует одинакового CPU-бюджета, GPU и сетевого пути. Результат будет иметь смысл только внутри SLO по TTFT, inter-token latency и доле успешных запросов. Иначе суммарная скорость сервера вырастет, а время ответа для пользователя – увеличится.
Оценить простоту локального жизненного цикла модели
Ollama объединяет загрузку модели, локальное хранилище, Modelfile и HTTP API. Один инженер может быстро заменить модель, изменить системный промпт или выгрузить веса после простоя. Холодный старт здесь тоже часть жизненного цикла, его оценивают отдельно от последующих запросов.
В прогретом режиме результат зависит от OLLAMA_NUM_PARALLEL, OLLAMA_MAX_QUEUE, OLLAMA_MAX_LOADED_MODELS, размера контекста и keep_alive. Параллельные запросы увеличивают память под контекст, поэтому настройка под короткие промпты даст очередь или ошибку на длинных запросах.
Быстрый старт и удобный CLI не обязательно означают высокий throughput. Для личного чата и небольшого API Ollama обычно достаточно, а под конкурентной нагрузкой раскрывается continuous batching в vLLM: запросы приходят в разное время и плотнее заполняют ускоритель. Здесь стоит судить по поведению серверов на одинаковой нагрузке, а не по названиям функций.
Разобрать планировщик, batching и управление KV-cache
vLLM рассчитан на серверную очередь: планировщик обновляет состав пакета по мере освобождения ресурсов, а KV-cache хранится блоками. Такой планировщик приносит пользу, когда есть очередь, совместимый GPU и подходящий бэкенд. На одиночных запросах он ничего не даёт.
В отчёте нужно фиксировать --max-num-seqs, --max-model-len, --gpu-memory-utilization, dtype и настройку chunked prefill, на нескольких GPU – ещё и --tensor-parallel-size. Распределение модели между устройствами может увеличить бюджет памяти, но требует обмена данными между GPU.
Параллельные запросы Ollama используют общую память, поэтому у обоих серверов отслеживают очередь, ошибки и OOM. Также у vLLM дополнительно смотрят preemption и состояние KV-cache. На одном коротком запросе дополнительная настройка vLLM может не окупиться.
Какой сервер проще для одного пользователя?
Один пользователь обычно быстрее настроит Ollama, ведь установка, загрузка модели и локальный API собраны в одном инструменте. Это упрощает запуск и дальнейшее обслуживание. vLLM стоит выбрать сразу, если нужны доступные только в нём модели, определённый GPU-бэкенд, подробные метрики или ожидается заметный рост конкурентности.
Уравнять модель, точность и генерацию
Честное сравнение серверов инференса LLM начинается с эквивалентных весов, dtype и схемы квантования. GGUF и safetensors задают упаковку весов и совместимость с движком, а на качество и память влияют точность и квантование. Если общая сборка недоступна, вывод относится только к протестированным вариантам, поэтому в отчёте остаются хеши и источники файлов.
Клиент отправляет одинаковые запросы с общими max_tokens, temperature, top_p, stop и потоковым режимом. Для chat completions этого недостаточно: токенизатор и шаблон тоже должны совпадать, иначе messages превратятся в разные последовательности токенов. По числу входных токенов видно, совпали ли токенизатор и шаблон. В карточку запуска следует записывать версии ПО, GPU, VRAM, CPU, RAM и ОС.
Следующий шаг – разделение холодного и прогретого режимов. Оба движка работают с отключённым кэшем промптов либо используют его одинаково. Генератор нагрузки не должен ограничивать тест своим CPU или сетью. Значения ниже – пример такого набора, длины и число повторов зависят от реальной нагрузки и разброса.
input_tokens: [256, 2048]
output_tokens: 128
concurrency: [1, 2, 4, 8, 16, 32]
repeats: 5
stream: true
temperature: 0
Построить кривую от одного клиента до насыщения
Sweep-тест начинается с минимальной конкуренции и идёт по ступеням при неизменных запросах и параметрах генерации. Каждая ступень включает прогрев и несколько серий. Закрытый генератор держит число активных запросов, открытый задаёт частоту запросов, и режимы оценивают отдельно. Эти ступени наращивают до первого отказа: OOM, таймаут, HTTP 503, отклонённые запросы или выход p99 за SLO.
Итоговый график объединяет throughput и задержку vLLM с Ollama. Ось X показывает конкуренцию, а ряды по Y – запросы в секунду, выходные токены в секунду, TTFT, ITL или TPOT и end-to-end latency. Критерий выбора – выполнение SLO, даже если максимум токенов в секунду достигается при большей конкурентности.
Клиент записывает время отправки, первого токена ответа и завершения генерации, число токенов, HTTP-статус и ошибку, а рядом обычно сохраняют конфигурации, логи, загрузку GPU и памяти. Сырые данные делают график проверяемым: нужны requests.jsonl, run.json, results.csv, server.log и gpu.csv.
server,run,concurrency,input_tokens,output_tokens,ttft_ms,itl_ms,e2e_ms,status,error
Считать хвосты задержки, а не только tokens/s
Отсчёт TTFT начинается с отправки запроса и заканчивается на первом токене ответа. Первый фрагмент потока не считается ответом, если в нём нет текста, так как серверы по-разному шлют служебные поля. ITL описывает интервалы между токенами, а интервалы между сетевыми фрагментами правильнее назвать inter-chunk latency. TPOT равен времени генерации после первого токена, делённому на число последующих токенов. Отчёт содержит формулу, точки времени, p50, p95 и p99.
Суммарный throughput характеризует сервер, а клиентские метрики – скорость диалога. Batching увеличивает общую производительность, но одновременно и TTFT клиента. Отдельный блок теста нужен для fairness: короткие запросы не должны надолго задерживаться из-за длинных, а новые этапы prefill – создавать заметные паузы в генерации.
Единый клиент обращается к обоим серверам через локальный OpenAI-совместимый API и собирает сопоставимые метрики. Совпадение URL не гарантирует одинаковой токенизации, шаблона чата и функций, поэтому перед sweep-тестом нужна сверка полей, лимитов, stop-условий и числа токенов.
Что измерять кроме суммарных токенов в секунду?
TTFT и end-to-end latency в p50, p95 и p99.
ITL или TPOT, длину очереди и долю успешных запросов.
Число входных и выходных токенов, OOM, таймаут и отклонённые запросы.
Сравнить API, наблюдаемость, безопасность и обновления
OpenAI-compatible API – слой совместимости без гарантии полного совпадения. Список проверок зависит от приложения: chat completions, streaming, структурированный вывод, embeddings, вызов инструментов и параметры генерации нужны только там, где используются. Сверка по этому списку выявит неподдерживаемые поля до миграции.
Совпадение по полям не сделает сервис сразу готовым к публикации. При публикации сервиса reverse proxy или платформенный слой отвечает за TLS, аутентификацию, ограничение частоты запросов и журналирование. Открытый порт ещё не означает, что первый запрос уложится в SLO, поэтому проверка доступности должна отличать запущенный процесс от загруженной модели.
Наблюдаемость vLLM охватывает очередь, KV-cache, TTFT и полную задержку. Ollama возвращает длительности загрузки, обработки входа и генерации, а набор клиентских метрик остаётся тем же. Перед обновлением новую версию прогоняют на копии рабочего трафика, так как она может изменить бэкенд, шаблон чата, память или параметры. На случай отката стоит держать прежний образ или пакет, конфигурацию и хеш модели.
Принять решение и оставить путь миграции
В матрицу выбора попадают только числа из sweep-теста. В каждой строке сходятся обязательные функции, предел нагрузки внутри SLO и эксплуатационные ограничения. Если интервалы серий перекрываются, то разницы в производительности нет и выбор делают по простоте обновления и восстановления.
Единый API-контракт упрощает миграцию. Имена моделей, параметры генерации и обработку ошибок держат в адаптере, адрес сервера – в конфигурации. Перед переключением новую конфигурацию прогоняют на копии рабочей нагрузки.
Миграция начинается с небольшой доли трафика, а старый сервер остаётся для быстрого отката. На этой же доле проверяют очередь и backpressure. Бесконечная очередь перегрузку не устраняет, она превращает её в рост p99.
Один пользователь: стартовый выбор: Ollama.
Проверить: поддерживается ли модель, приемлемы ли холодный старт и потребление памяти.Небольшой API команды: стартовый выбор: Ollama или vLLM.
Проверить: укладываются ли всплески нагрузки в SLO и корректно ли обрабатываются ошибки перегрузки.Высокая конкурентность на GPU: стартовый выбор: vLLM.
Проверить: растёт ли throughput без недопустимого увеличения p99 и без OOM.
Ollama или vLLM для конкурентного инференса выбирают по кривой задержки и throughput внутри SLO. Сильные стороны Ollama – быстрый локальный запуск, простой жизненный цикл модели и умеренная очередь. vLLM требует больше настройки и подходит там, где batching, KV-cache и высокая загрузка GPU дают измеримый выигрыш. Сырые результаты дополняют версиями, весами, оборудованием, промптами и параметрами. Если преимущество исчезает после учёта p99, ошибок и сопровождения, миграция не нужна.












































