Ravi Vooda / Thoughts

Inference experiment · August 2026

GPT-OSS-20B on one H100

A measured study of vLLM throughput, latency, continuous batching, and KV-cache pressure using NVIDIA AIPerf.

9,354 peak short-context output tokens/s at concurrency 800
8,153 peak large-context output tokens/s with auto-sized KV
200–400 recommended long-context operating range for balance
28.26 GiB forced half-KV allocation used in the controlled comparison

The GPU reached high aggregate throughput well before the serving system reached a good operating point for users.

01

Throughput plateaued

Short-context throughput flattened between concurrency 400 and 1,600, peaking at 800 before declining.

02

KV pressure appeared as queueing

At saturation, fewer requests stayed resident while waiting queues and time to first token rose sharply.

03

Half KV moved the boundary

With 28.26 GiB, KV reached 100% at concurrency 800 instead of 1,600 under the auto-sized policy.

04

Raw throughput hid the damage

Aggregate output stayed near 8K tokens/s while average TTFT at concurrency 800 rose from 10.0s to 18.3s.

KV cache is primarily a capacity resource. Reducing it did not make token generation faster; it reduced the number of requests vLLM could keep resident.

With 256 input and 128 output tokens, the baseline peaked at concurrency 800. Beyond that point, aggregate throughput and caller fair share both fell.

Output throughput vs. concurrency

OUTPUT TOKENS / SECOND

Baseline: gpu-memory-utilization=0.92, approximately 56.5 GiB KV, 4,096-token maximum model length.

Concurrency Output tok/s Request/s Avg TTFT Avg ITL Fair share tok/s
1003,30526.452.53s9.9ms33.05
2007,96863.801.28s14.7ms39.84
4008,86971.001.71s31.1ms22.17
8009,35474.882.22s67.0ms11.69
1,6008,99471.993.10s145.2ms5.62
3,2008,20665.6810.51s263.6ms2.56
6,4005,06740.5612.61s331.7ms0.79

Short-context KV policy peaks

These runs all remained in a compute-dominated regime. Their peak differences are not evidence that a smaller cache accelerates the model.

Auto KV · utilization 0.92
9,354
Auto KV · utilization 0.98
9,792
Exact KV · 28.26 GiB
10,221

The sustained 2,048-input / 512-output workload made KV capacity visible. The auto-sized cache reached its boundary at concurrency 1,600.

Aggregate throughput stayed close

OUTPUT TOKENS / SECOND

The half-KV run is not faster in a causal sense. Both configurations kept the GPU near compute saturation.

Time to first token

AVERAGE · SECONDS

Maximum KV use

PERCENT
Concurrency Auto KV tok/s Half KV tok/s Auto TTFT Half TTFT Auto / half KV use
504,0894,5051.12s0.74s5.1% / 10.6%
1005,9926,1080.98s0.94s10.0% / 21.8%
2007,6207,7732.59s1.70s19.8% / 42.9%
4007,8788,1974.82s4.77s39.6% / 85.5%
8008,1538,3629.96s18.35s80.2% / 100%
1,6007,2287,66334.21s52.93s100% / 100%
At concurrency 800, cutting KV approximately in half increased average TTFT by 84% while aggregate output throughput changed by only 2.6%.

Dividing server-wide output throughput by configured concurrency provides a simple fair-share estimate. It falls rapidly after the useful operating range.

Estimated output rate per configured caller

OUTPUT TOKENS / SECOND / CALLER

Estimate = aggregate output token throughput ÷ configured concurrency. Waiting callers receive no tokens, so this is capacity intuition rather than an individual streaming trace.

For the auto-KV stress run, concurrency 200 delivered about 38.1 fair-share tokens/s. Raising concurrency to 400 added only 3.4% aggregate output throughput, but reduced fair share to 19.7 tokens/s and increased average TTFT by 86%.

Optimize for latency-constrained goodput and queue depth, not the single highest tokens-per-second number.

Default range

Start long-context capacity planning around concurrency 200–400 on this hardware and workload, then tune against an explicit TTFT objective.

KV sizing

Use automatic profiling or a conservative explicit --kv-cache-memory-bytes value. A forced 62.05 GiB allocation failed at startup with CUDA OOM.

Admission

Apply request admission control before KV reaches 100%. Queue depth and waiting requests are leading capacity signals.

Benchmarking

Use sustained, duration-bounded workloads with realistic input/output distributions and evaluate TTFT, ITL, and SLO goodput alongside throughput.

Caller metric

Do not interpret aggregate output tokens/s as the stream rate seen by every caller. Track per-request latency distributions in production.

AIPerf concurrency was matched to vLLM's --max-num-seqs setting for each sequential server run.

Hardware
1× NVIDIA H100 80GB HBM3
Model
openai/gpt-oss-20b · MXFP4
Tensor parallelism
1
KV dtype
auto
Short workload
ISL 256 · OSL 128 · max len 4,096
Stress workload
ISL 2,048 · OSL 512 · max len 16,384
Stress profile
180s profile · 30s warmup
Forced half KV
30,343,943,946 bytes · 617,042 tokens

vLLM uses continuous batching. Here, “concurrency” is the number of in-flight AIPerf requests, while max-num-seqs is a scheduler cap—not a promise that every request is resident on the GPU at once. Under half-KV pressure, roughly 450–500 requests were running while the remainder waited.

The complete benchmark matrix, machine-readable results, and runner scripts are available in the experiment directory.