Фраза «локальная LLM для 100 сотрудников» ещё не определяет сервер.
Сто сотрудников не означают сто одновременных inference-запросов. Но и попытка заменить их условными «10 concurrent users» проблему не решает: два одинаковых по числу пользователей сервиса могут сильно различаться по частоте запросов, длине prompt, истории диалога, RAG-контексту, длине ответа и требованиям к задержке.
Правильная последовательность другая:
сотрудники
↓
кто имеет доступ
↓
фактическое использование
↓
временной поток requests
↓
request mix
↓
ISL / OSL distributions
↓
Typical / Peak / Burst workload
+
capacity curve сервера
↓
queue / TTFT / ITL / E2E
↓
SLA gate
↓
максимальная нагрузка,
проходящая SLA
Главный принцип:
У Start Server production LLM inference уже выделен как отдельный коммерческий сценарий; на текущей странице при подборе отдельно перечисляются модель, квантизация, контекст, одновременные запросы, latency, throughput, KV cache и особенности RAG/agent workload.
Почему 100 сотрудников не равны 100 concurrent requests

Для начала разделите несколько величин:
TOTAL EMPLOYEES
↓
ELIGIBLE USERS
↓
ACTIVE USERS
↓
ACTIVE SESSIONS
↓
USER TASKS
↓
MODEL REQUESTS
Между ними нет универсальных коэффициентов.
Один сотрудник может иметь доступ к сервису, но почти им не пользоваться. Другой отправляет десятки запросов в день. В agentic application одна пользовательская задача может породить несколько вызовов модели.
Поэтому таблица проекта начинается так:
Параметр | Значение | Статус |
Total employees | MEASURED | |
Eligible users | MEASURED / FORECAST | |
DAU | MEASURED / FORECAST | |
Peak-window active users | MEASURED / FORECAST | |
User tasks | MEASURED / FORECAST | |
Model calls/task | MEASURED / ARCHITECTURE |
Для каждого значения полезно использовать один из статусов:
MEASURED
FORECAST
ASSUMPTION
UNKNOWN
Так сценарный расчёт не превращается незаметно в «факт».
Для сервера важнее request trace, чем DAU
Число активных пользователей полезно для product analytics.
Но inference capacity непосредственно нагружают запросы.
Минимально полезная обезличенная запись:
timestamp
model / version
input tokens
output tokens
request class
session ID
если нужен multi-turn анализ
completed
cancelled
error
Если реальный traffic уже существует, workload benchmark лучше строить по его характеристикам. NVIDIA рекомендует подбирать input/output sequence lengths по реальному use case и при наличии production traffic использовать representative prompts. Длина input влияет прежде всего на prefill, память и TTFT, а длина output — на generation workload и ITL.
Как получить request rate
Для окна продолжительностью T секунд и N поступивших запросов:
λ=NT\lambda=\frac{N}{T}
где λ — средняя частота прихода requests за это окно.
В worksheet:
Observation window:
...
Requests:
...
Window duration:
...
Average arrival rate:
... req/s
Но это только первый слой.
Одинаковые 10 req/s могут описывать совершенно разную нагрузку.
PROFILE A
запросы идут
почти равномерно
PROFILE B
большинство запросов
приходит короткими всплесками
Поэтому фиксируйте peak и burst отдельно
Минимальная модель:
Параметр | Значение |
Typical RPS | |
Peak RPS | |
Peak window | |
Burst rate | |
Burst duration | |
Timestamp trace | YES / NO |
Современные benchmark tools специально разделяют request rate, характер межприходных интервалов и concurrency. Текущий vllm bench serve, например, позволяет задавать request rate, Gamma/Poisson-подобную burstiness и отдельный maximum concurrency.
AIPerf аналогично разделяет rate-based scheduling, timestamp replay, user-centric timing и concurrency-driven saturation.
Если есть timestamps, сохраните trace
Допустим, реальная нагрузка выглядит так:
09:00:00.120
09:00:00.195
09:00:00.208
09:00:02.970
...
Сведение её к:
average = 1 request/s
уничтожает часть информации.
Для зрелого production profile приоритет лучше задать так:
REAL TIMESTAMP TRACE
↓
DISTRIBUTION FITTED TO TRACE
↓
PILOT-DERIVED PROFILE
↓
BUSINESS FORECAST
↓
EXPLICIT ASSUMPTION
Но benchmark client не должен незаметно менять workload
Это важная техническая проверка.
Допустим, production trace предполагает, что в определённую секунду должно поступить много запросов.
Если load generator дополнительно настроен:
max concurrency = 10
часть запросов может ждать свободного client-side слота ещё до отправки на сервер.
Тогда benchmark фактически проверяет:
original demand
+
client-side throttling
а не исходный offered load.
В AIPerf при совместном использовании rate и concurrency частота определяет schedule, а concurrency является ceiling; при занятом semaphore запрос ждёт возможности отправки.
Поэтому в отчёте нужны две отдельные строки:
Client/gateway concurrency limit:
...
Server queue:
...
Если client limit отсутствует в production, его не следует незаметно добавлять в workload model.
Один пользователь — не один тип запроса
Корпоративная LLM может одновременно обслуживать:
Request class | Share | ISL p50 | ISL p95 | OSL p50 | OSL p95 |
Short Q&A | |||||
Drafting | |||||
Summarization | |||||
Long-document | |||||
RAG-assisted |
Это шаблон, а не обязательная taxonomy.
В реальном проекте request classes формируются по фактическим use cases.
Главное — не превращать всё в один:
average request
Что входит в input sequence length
Для чат-системы effective ISL может включать:
system instructions
+
conversation history
+
current user turn
+
RAG context
+
application/tool context
Поэтому:
сотрудник ввёл 30 tokens
не означает:
ISL = 30
В актуальном NVIDIA NIM guide ISL также определяется как весь input model, включая system instructions, chat history и RAG context.
Output length также нужна как distribution
Запрос:
«Когда заканчивается договор?»
и задача:
«Подготовь аналитический отчёт»
создают разную decode-нагрузку.
Поэтому вместо одной строки:
Average output:
...
лучше хранить:
OSL p50:
OSL p95:
Policy maximum:
если есть
При наличии полной telemetry можно хранить distribution целиком.
vLLM уже предоставляет histograms количества prompt и generation tokens на request, поэтому такие distributions можно получать с inference layer.
Почему p50/p95 лучше одной средней
Предположим:
90% prompts:
короткие
10% prompts:
очень длинные
Средний input может выглядеть относительно небольшим.
Но тяжёлый хвост способен заметно влиять на:
prefill load
KV-cache demand
queue
TTFT
Поэтому статья использует p50/p95 как удобный шаблон представления distribution, но не объявляет именно p95 обязательным percentile для любого проекта.
Если product SLA построен по p90 или p99, используйте его.
RAG context входит в LLM workload
SS-021 отвечает за retrieval pipeline:
ingestion
vector DB
retrieval
reranking
SS-022 интересует уже то, что попало в model input:
base prompt
+
chat history
+
retrieved context
=
effective ISL
Поэтому worksheet содержит:
RAG:
YES / NO
Retrieved-context tokens:
distribution / p50 / p95
Одна пользовательская задача может создать несколько model requests
Для обычного помощника:
1 user turn
→ 1 model request
может быть корректной моделью.
Для agent workflow:
1 user task
↓
planning
↓
tool interaction
↓
follow-up inference
↓
final generation
уже нет.
Поэтому обязательно поле:
Model calls per user task:
SINGLE
или
MULTI-CALL
Если multi-call workload существенен, дальнейшая decomposition относится к SS-032.
Retries, errors и cancellations тоже влияют на traffic
Endpoint может получить больше requests, чем инициировал пользователь, например из-за retry policy.
Поэтому telemetry желательно различать:
Initial requests:
Retries:
Completed:
Cancelled:
Errors:
Можно ли вычислить concurrency через RPS
Для устойчивой системы полезен sanity check:
L=λWL=\lambda W
где L — среднее число requests в системе, λ — средний arrival rate, W — среднее время request в системе.
То есть:
mean request arrival
×
mean residence time
≈
mean requests in system
Но ключевое слово — mean.
Это не:
peak concurrency
не:
p95 concurrency
и не:
maximum queue depth
Поэтому формула:
Peak concurrency =
Peak RPS × latency
не используется как sizing rule.
Время request тоже зависит от нагрузки
Особенно опасно взять:
W = latency
при concurrency = 1
и использовать его для расчёта peak production load.
По мере приближения к saturation:
queue time ↑
TTFT ↑
E2E ↑
и сама W меняется.
Demand и capacity проверяются двумя разными режимами
Demand replay
Отвечает:
Что случится, если пользователи будут отправлять запросы в production-like режиме?
Вход:
timestamp trace
или
arrival distribution
+
request mix
+
ISL / OSL
На выходе:
running
waiting
queue
TTFT
ITL
E2E
errors
SLA compliance
Capacity characterization
Отвечает:
Как меняется performance конкретного server/runtime при росте in-flight load?
Concurrency 1
↓
2
↓
4
↓
8
↓
...
AIPerf в concurrency-only режиме поддерживает заданное число in-flight requests, отправляя новый после завершения предыдущего. Rate-based и fixed-schedule workloads работают иначе.
Поэтому:
Для production sizing полезны оба слоя.
Concurrency не равна batch size
Запись:
concurrency = 20
не означает:
batch size = 20
Concurrency говорит, сколько requests одновременно находится в работе/системе согласно принятому определению.
Batching — внутреннее решение scheduler/runtime о том, какие tokens или requests обрабатываются совместно в конкретный момент.
Не нужно выводить batch size из числа сотрудников или requests in flight.
Running и waiting requests нужно разделять

но разделять
Например:
20 requests in service
могут означать:
20 running
0 waiting
или:
8 running
12 waiting
Это разные состояния.
vLLM отдельно экспортирует num_requests_running и num_requests_waiting; waiting также может быть разбит по причине ожидания.
Для capacity worksheet:
Running:
Waiting:
Server queue depth:
Не смешивайте client queue и server queue
Это отдельная строка Final именно из-за риска получить ложный вывод.
Client/load-generator queue
Запрос ещё не был отправлен server, потому что benchmark client применяет собственный concurrency limit.
Server queue
Запрос уже поступил serving system, но ждёт scheduling capacity.
vllm bench serve может отдельно учитывать client queue при max-concurrency, тогда как production metric vllm:request_queue_time_seconds относится к ожиданию в serving runtime.
Поэтому:
Client queue:
...
Server queue:
...
а не одно безымянное:
Queue = ...
TTFT, ITL/TPOT и E2E отвечают на разные вопросы
Метрика | Что показывает |
Queue time | ожидание capacity |
TTFT | задержку до начала ответа |
ITL / TPOT | темп выдачи последующих токенов |
E2E | полное время request |
vLLM экспортирует отдельные histograms TTFT, inter-token latency, E2E latency, queue, prefill и decode time.
Но точную семантику нужно хранить вместе с инструментом.
Например, в текущей vLLM telemetry TTFT считается относительно frontend arrival time, а отдельная per-request telemetry также имеет queue и generation intervals.
AIPerf использует собственные client-observed definitions.
Поэтому benchmark record обязательно содержит:
Tool:
Version:
Metric:
Definition:
Высокий TTFT не означает автоматически медленную GPU
TTFT может включать влияние:
queueing
long prefill
large ISL
scheduler load
first-token generation
Поэтому диагностика должна смотреть вместе:
ISL
queue
running/waiting
prefill
TTFT
а не делать вывод только по одному показателю.
Total TPS и пользовательская скорость — разные показатели
С увеличением concurrency aggregate system throughput способен расти до saturation.
Но одновременно latency каждого request может ухудшаться.
NVIDIA NIM benchmarking отдельно различает total system TPS и TPS per user и прямо отмечает, что при росте concurrency total TPS может увеличиваться, тогда как per-user throughput снижается из-за роста latency.
Поэтому нельзя выбирать сервер только по:
MAX TOTAL TPS
Production capacity должна быть ограничена SLA
Рабочее определение SS-022:
CapacitySLA=maxLoadCapacity_{SLA} = \max Load
при котором выполняются согласованные требования:
TTFT
ITL / TPOT
E2E
queue
error/reject policy
required SLA attainment
Это позволяет отличить:
raw throughput
от:
useful production capacity
SLA-compliant rate полезнее raw request throughput
AIPerf использует термин goodput для количества завершённых requests в секунду, удовлетворивших заданным SLO constraints. Он также рассчитывает долю запросов, прошедших все SLO; ошибки входят в denominator, чтобы система не выглядела успешной только потому, что под перегрузкой отбросила часть запросов.
В vendor-neutral статье лучше использовать термин:
а goodput приводить как конкретную реализацию этой идеи в AIPerf.
Ошибки и rejections входят в результат
Представим две системы.
Первая обслуживает весь workload, но часть requests нарушает latency SLA.
Вторая сохраняет хорошую latency, потому что часть demand вообще отклоняет.
Одна цифра TTFT не позволяет решить, какая прошла acceptance.
Нужен record:
Attempted:
Completed:
SLA-compliant:
Errors:
Rejected:
Cancelled:
Именно поэтому capacity — это не максимальное число успешно завершившихся requests без учёта того, что происходило со всем offered load.
Типичная, пиковая и burst-нагрузка — разные сценарии
Сценарий | Назначение |
Typical | обычный рабочий режим |
Peak | наиболее загруженное устойчивое окно |
Burst | кратковременный всплеск |
Heavy mix | повышенная доля длинных requests |
Future adoption | ожидаемый рост использования |
Не нужен универсальный:
hardware reserve = 30%
Вместо этого задайте будущий workload напрямую.
Growth тоже должен быть выражен через demand
Корректно:
CURRENT
Peak RPS:
...
Request mix:
...
ISL/OSL:
...
TARGET ADOPTION
Peak RPS:
...
Request mix:
...
FUTURE
...
Это даёт понятную причину дополнительной capacity.
Гораздо хуже:
GPU × 1.3
без workload justification.
Employees → Offered Load → SLA Capacity Worksheet
Основной самостоятельный инструмент статьи:
POPULATION
Total employees:
Eligible users:
DAU:
Value:
MEASURED / FORECAST
Peak-window users:
Value:
MEASURED / FORECAST
APPLICATION
Use cases:
Single-turn / multi-turn:
Model calls per task:
SINGLE / MULTI-CALL
RAG:
YES / NO
Streaming:
YES / NO
TRACE
Observation period:
Requests:
Timestamp trace:
YES / NO
Retries:
Cancellations:
Errors:
ARRIVAL PROFILE
Typical RPS:
Peak RPS:
Peak window:
Burst rate:
Burst duration:
Arrival source:
TRACE /
MODELED DISTRIBUTION /
FORECAST
REQUEST MIX
CLASS A
Name:
Share:
ISL p50:
ISL p95:
OSL p50:
OSL p95:
CLASS B
Name:
Share:
ISL p50:
ISL p95:
OSL p50:
OSL p95:
INPUT COMPOSITION
System prompt:
Conversation history:
RAG context:
Other:
SANITY CHECK
Mean arrival λ:
Mean residence W:
L = λ × W
Interpretation:
MEAN REQUESTS IN SYSTEM
NOT:
PEAK CONCURRENCY
SLA
Target percentile:
TTFT:
ITL / TPOT:
E2E:
Server queue:
Allowed errors/rejections:
Required attainment:
SERVER CONFIGURATION
Model/version:
Precision:
Runtime/version:
Hardware:
Prefix cache:
ENABLED / DISABLED
Cache state:
COLD / WARM / MIXED
CAPACITY CHARACTERIZATION
Concurrency sweep:
For each point:
Request throughput:
Aggregate TPS:
Per-request/per-user throughput:
TTFT:
ITL / TPOT:
E2E:
Running:
Waiting:
Server queue:
Errors/rejections:
SLA-compliant rate:
DEMAND REPLAY
Typical:
PASS / FAIL
Peak:
PASS / FAIL
Burst:
PASS / FAIL
Heavy mix:
PASS / FAIL
Future adoption:
PASS / FAIL
RESULT
Maximum offered load
meeting SLA:
Primary bottleneck:
Capacity status:
SIZED /
CANDIDATE /
FAIL /
INSUFFICIENT DATA
Demand vs Capacity Matrix
Уровень | Метрика | Источник |
Population | eligible users | IAM / project |
Adoption | DAU / peak-window users | analytics |
Demand | request timestamps | gateway / API |
Arrival | typical / peak RPS | trace |
Burst | rate + duration | trace |
Request mix | доли use cases | application logs |
Token profile | ISL / OSL | inference telemetry |
Server state | running / waiting | runtime |
Queue | client + server отдельно | benchmark/runtime |
UX | TTFT / ITL / E2E | metrics |
Reliability | error / reject / cancel | runtime/gateway |
Capacity | SLA-compliant load | benchmark |
Главная идея этой таблицы:
100 EMPLOYEES
и:
SERVER CAPACITY
не соединяются одной арифметической операцией.
Benchmark Handoff Contract

SS-022 должна закончиться workload specification, которую можно отдать инженеру для SS-038.
WORKLOAD ID:
MODEL:
VERSION:
PRECISION:
SERVING STACK:
VERSION:
HARDWARE:
...
REQUEST SOURCE
TRACE /
SYNTHETIC
ARRIVAL PROFILE
Typical RPS:
Peak RPS:
Burst:
rate:
duration:
Arrival distribution / trace:
CLIENT LIMITS
Client max concurrency:
Gateway limit:
Are these production constraints?
YES / NO
REQUEST MIX
Class A:
Share:
Class B:
Share:
ISL
p50:
p95:
Distribution/source:
OSL
p50:
p95:
Distribution/source:
MULTI-TURN
YES / NO
History behavior:
RAG
YES / NO
Retrieved-context profile:
CACHE
Prefix caching:
Expected cache state:
COLD / WARM / MIXED
SLA
Target percentile:
TTFT:
ITL / TPOT:
E2E:
Server queue:
Error/reject policy:
Required attainment:
REQUIRED OUTPUT
Actual workload validation:
Concurrency/latency curve:
Maximum SLA-compliant
offered load:
Client queue:
Server queue:
Running/waiting:
Errors/rejections:
Primary bottleneck:
Как читать результат
Используем четыре статуса.
Статус | Значение |
SIZED | workload воспроизведён, configuration прошла требуемые SLA |
CANDIDATE | sizing рассчитан, validation ещё не выполнена |
FAIL | целевой workload не проходит acceptance |
INSUFFICIENT DATA | отсутствуют критические inputs |
Если тест использует другую модель, другую precision, существенно другой ISL/OSL profile или другую arrival model:
NOT COMPARABLE
Это не FAIL и не PASS.
Это другой workload.
Какие данные нужны для подбора локального LLM-сервера
Для первичного sizing достаточно передать:
MODEL
model/version
precision
USERS
eligible users
pilot/production telemetry,
если есть
DEMAND
typical RPS
peak RPS
burst profile
REQUEST PROFILE
ISL p50/p95
OSL p50/p95
multi-turn:
YES / NO
RAG:
YES / NO
model calls/task:
SINGLE / MULTI-CALL
SLA
TTFT
ITL / TPOT
E2E
queue tolerance
error/reject policy
GROWTH
current workload
target-adoption workload
Если этих данных ещё нет, допустим scenario model. Но assumptions должны быть явно подписаны.
Получить консультацию
Оставьте заявку и наш менеджер свяжется с вами для консультации









