Skip to main content

Validation

LLMServingSim is validated end-to-end against real vLLM on the bundled (hardware, model) combos. The numbers below come from running a 300-request ShareGPT replay through both vLLM v0.19.0 and the simulator on RTXPRO6000, then comparing the per-request and per-tick metrics with python -m bench validate.

Want to validate your own change? See For Contributors → Validating your changes for the regression workflow.

Setup

KnobValue
Workload300 ShareGPT-derived requests, ~10 sps Poisson arrivals
HardwareRTXPRO6000 and RTX 4090, single node (profile bundles in profiler/perf/<hardware>/)
vLLM versionv0.19.0 (the pin used by the bench container)
Block size16
Engine flagsDefaults except where the cluster config dictates otherwise
Cluster configsbench/examples/<hardware>/<model>/config.json
KV capacitymem_util 0.9, except the RTX 4090 example which is calibrated to the measured block count (see below)

Inputs and outputs (vLLM token IDs, sampling params, per-request timings) are pinned via bench's strict-replay path so both runs process exactly the same prompts in the same order.

Match mem_util to the real run whenever the KV cache saturates

npu_mem.mem_util sizes the KV cache, and KV cache size only shows up in the results once a run actually fills it — below that nothing is preempted and the capacity is invisible. Of the four configurations here, only the RTX 4090 one is in that regime: 24 GB, pinned at its ceiling for most of the run. It therefore sets mem_util so the simulator's block count equals the one vLLM resolved, read out of that run's own meta.json:

"kv_cache": { "num_gpu_blocks": 2588, "block_size": 16, "num_kv_tokens": 41408 }

That matters because the simulator does not model vLLM's activation peak or CUDA context, so the default mem_util: 0.9 yields more KV cache than vLLM gets at the same fraction — less preemption, an early finish, and every latency metric moving with it:

KV tokensblocksTTFT meanTPOT meanLatency mean
mem_util: 0.9 (default)54,4003,400-20.7%+12.9%-12.5%
mem_util: 0.833919 (matched)41,4082,588+0.6%+0.2%+0.5%

The three RTXPRO6000 configurations peak at 58-97% of their budget on a 96 GB card, so they stay at 0.9 — calibrating them would change nothing. If you validate against your own vLLM run, check the peak Each NPU Memory Usage in the heartbeat first: if it approaches mem_util * 100, read num_gpu_blocks from meta.json and match it before comparing latency at all.

Headline numbers

Mean error vs. real vLLM, per metric, on the four currently bundled configurations:

HardwareModelParallelismTTFT meanTPOT meanLatency mean
RTX 4090Llama-3.1-8BTP=1 dense+0.6%+0.2%+0.5%
RTXPRO6000Llama-3.1-8BTP=1 dense-4.0%-1.0%-1.8%
RTXPRO6000Qwen3-32BTP=2 dense+1.3%+0.8%+1.0%
RTXPRO6000Qwen3-30B-A3B-Instruct-2507DP=2 x EP=2 MoE-13.6%-1.7%-2.2%

Every number on this page is read out of the committed bench/examples/<hardware>/<model>/validation/summary.txt files, so it is reproducible rather than quoted.

TPOT means land within 1.7% and end-to-end latency means within 2.2% on all four configurations, and the DP+EP MoE path tracks vLLM as tightly as the dense TP path on both. TTFT means are looser: -4.0% on the RTXPRO6000 Llama run and -13.6% on the MoE run.

The RTX 4090 row is the tightest of the four, inside 1% on every metric including all percentiles. It is also the only run whose mem_util is calibrated against the measured KV block count — see the caution above — and the only one whose card saturates, so it is the cleanest available apples-to-apples comparison.

That TTFT spread is expected rather than alarming, and it is worth knowing why before reading the tables. The two sides do not define the measurement identically — the simulator stops the clock when the first token's computation finishes, vLLM when the client receives it — and TTFT is dominated by queueing, so a small scheduling difference early in the run moves the mean a lot. On the MoE run the median TTFT is 138.8 ms against 108.6 ms, so a 30 ms absolute difference reads as -21.8%. Judge TTFT by its absolute error and its tail, not by percentage of a very small number: TTFT P90 through P99 land within 10.9% on every configuration, and within 1.0% on the RTX 4090 run.

Per-percentile numbers (median / P90 / P95 / P99) are in the same summary.txt files under bench/examples/.

Per-configuration results

RTX 4090 — Llama-3.1-8B (TP=1 dense)

Throughput timeline, vLLM (orange) vs. simulator (blue):

RTX 4090 Llama-3.1-8B throughput

MetricvLLMSimDiff
TTFT mean65.46 s65.82 s+0.6%
TTFT P99137.36 s137.70 s+0.3%
TPOT mean32.4 ms32.5 ms+0.2%
TPOT P9956.0 ms56.5 ms+0.9%
Latency mean86.58 s86.98 s+0.5%
Latency P99153.63 s154.22 s+0.4%

The tightest configuration in the set: every metric at every percentile lands between +0.2% and +0.9%. Two things make it the cleanest comparison available. The 24 GB card genuinely saturates its KV cache, so the scheduler is under real memory pressure on both sides rather than running with slack; and its mem_util is calibrated to the block count vLLM actually resolved, so the two are working from the same capacity. The latency model itself is untouched — profiled latencies go in as measured — so TPOT at +0.2% is a free prediction rather than a fit.

RTXPRO6000 — Llama-3.1-8B (TP=1 dense)

Llama-3.1-8B throughput

MetricvLLMSimDiff
TTFT mean7.10 s6.82 s-4.0%
TTFT P9919.76 s19.36 s-2.0%
TPOT mean32.5 ms32.1 ms-1.0%
TPOT P9937.3 ms37.6 ms+0.6%
Latency mean28.20 s27.69 s-1.8%
Latency P9937.64 s37.03 s-1.6%

The same model and parallelism on a 96 GB card, which never fills its KV cache (it peaks at 78% of its budget). TPOT stays within 1.0% and latency within 1.8%; TTFT is -4.0% on the mean and -8.6% on the median, the simulator getting first tokens out slightly early.

RTXPRO6000 — Qwen3-32B (TP=2 dense)

Qwen3-32B throughput

MetricvLLMSimDiff
TTFT mean36.91 s37.37 s+1.3%
TTFT P9993.35 s94.21 s+0.9%
TPOT mean80.3 ms81.0 ms+0.8%
TPOT P9997.1 ms98.4 ms+1.3%
Latency mean90.41 s91.33 s+1.0%
Latency P99126.34 s127.93 s+1.3%

TP=2 exercises the dense ALLREDUCE collective on o_proj / down_proj. The most uniformly accurate of the RTXPRO6000 runs: every metric at every percentile lands between +0.8% and +1.7%, and all of them are positive — the simulator over-predicts by a small, consistent margin rather than drifting.

RTXPRO6000 — Qwen3-30B-A3B-Instruct-2507 (DP=2 × EP=2 MoE)

Qwen3-30B-A3B throughput

MetricvLLMSimDiff
TTFT mean1.09 s0.94 s-13.6%
TTFT P999.59 s9.49 s-1.0%
TPOT mean47.3 ms46.5 ms-1.7%
TPOT P9953.3 ms53.0 ms-0.5%
Latency mean32.34 s31.65 s-2.2%
Latency P9943.90 s43.09 s-1.8%

The disaggregated path: data-parallel across two instances, expert-parallel within each, with wave-synchronized collectives. TPOT and latency hold to -1.7% and -2.2%, but TTFT reads -13.6% on the mean and -21.8% on the median. The absolute numbers explain most of that: the median is 138.8 ms against 108.6 ms, a 30 ms difference on the smallest values in the whole set. The tail, where absolute queueing dominates, comes back to -1.0% at P99. This run has the most memory headroom of the four (52% of budget), so its TTFT error is not a capacity effect.

Reproducing locally

The bench module ships with reproduction scripts that re-run the simulator side and re-run the comparison against the committed vLLM artifacts:

# Sim side: writes bench/examples/<hardware>/<model>/outputs/sim.csv
./bench/examples/run.sh # all four
./bench/examples/run.sh RTX4090/Llama-3.1-8B # or one at a time

# Compare: writes bench/examples/<hardware>/<model>/validation/{summary.txt, *.png}
./bench/examples/validate.sh
./bench/examples/validate.sh RTX4090/Llama-3.1-8B

Both scripts take <hardware>/<model> and discover the examples from the directory layout, so every number on this page comes back from the committed artifacts without editing a script.

The validation step regenerates the throughput / latency / requests plots and the headline summary. To rerun vLLM itself (instead of reusing the committed artifacts under bench/examples/<hardware>/<model>/vllm/), use python -m bench run from inside the vLLM container; see bench/README.md for the full layout.

What's next