Runtimes¶
BenchRig measures the same scenarios on several inference runtimes and reports them side by side. Pick one with
--runtime, or address a model directly with a runtime:model prefix in --models.
| Runtime | --runtime |
Prefix | What it is | Config section |
|---|---|---|---|---|
| Ollama | ollama |
ollama: |
llama.cpp (GGUF) behind Ollama's REST API |
ollama |
| Microsoft Foundry Local | foundry |
foundry:, ms-foundry: |
ONNX Runtime GenAI behind the Foundry daemon | foundry |
| Direct ONNX Runtime GenAI | onnx-gpu |
onnx-gpu:, onnx: |
ONNX Runtime GenAI in the BenchRig process (CUDA) | onnx |
| Prism | prism |
prism:, prism-local: |
One OpenAI-compatible endpoint in front of ONNX Runtime GenAI (CUDA or CPU) and Ollama | prism |
| All | all |
Every runtime that is reachable |
benchrig --check # which runtimes are reachable, and what they serve
benchrig --runtime ollama --models qwen2.5-coder:7b
benchrig --models ollama:qwen2.5-coder:7b,prism:phi-4-mini # mix runtimes in one run
Ollama¶
Talks to Ollama's native API (/api/generate) and measures time to first token from the stream. The default endpoint is
http://localhost:11434; see ollama configuration.
Microsoft Foundry Local¶
Talks to the Foundry daemon's OpenAI-compatible API. By default the port is read from ~/.foundry/daemon.json because Foundry
starts on an ephemeral port (auto_detect_port: true); models are loaded and unloaded with the foundry CLI. See
Foundry GPU setup for making it use an NVIDIA GPU on WSL2.
Direct ONNX Runtime GenAI¶
Loads a model folder (one that contains genai_config.json) inside the BenchRig process, with the CUDA execution provider when
available. Install the extra and put models in $BENCHRIG_MODEL_DIRS, ./models or ~/.benchrig/models:
pip install "benchrig[onnx-gpu]"
benchrig --runtime onnx-gpu --models Phi-4-mini-instruct-cuda-gpu --suite coding
Prism¶
Prism (prism-local) is a local server that puts ONNX Runtime GenAI and Ollama behind
one OpenAI-compatible endpoint on a fixed port. It also lets you choose the execution device (--device auto|cuda|cpu), which
makes it a convenient way to benchmark ONNX models on WSL2, where the Foundry CLI can fail to detect the GPU
(see Prism's own evaluation notes).
pip install prism-local && prism serve # http://127.0.0.1:5272/v1
benchrig --check # lists the models Prism serves and the engine behind each
benchrig --runtime prism --models prism:phi-4-mini --suite coding
How BenchRig talks to it
- The endpoint comes from
prism.base_url(defaulthttp://127.0.0.1:5272/v1) and is never auto-discovered. ThefoundryCLI is never used, so a Foundry daemon running on the same machine cannot capture the requests. - If the server was started with
--api-key, setPRISM_API_KEY(orprism.api_key); it is sent as a bearer token. - Prism loads models on the first request and has nothing to unload, so
load_modelonly checks that the server lists the model. --pull-recommended --runtime prismrunsprism pull <model>and needs theprismCLI onPATH.
Models and engines
Prism also proxies installed Ollama models as ollama:<name>. The engine that serves each model is taken from the server's
owned_by field (falling back to the ollama: prefix) and shown in reports, so a Prism-proxied Ollama model is not labelled as
ONNX.
--models installedwith--runtime prismor--runtime allskips theollama:proxies: benchmark those natively with theollamaruntime. To measure the proxy itself, ask for it explicitly:--models prism:ollama:qwen2.5-coder:3b.- A
--pairmay carry aprism:model name next toollama:andfoundry:; with--baselineand--runtime prismit falls back to the pair'sonnx:and thenfoundry:names.
Token counts and the model-only memory figure
- Prism started from a version with
stream_options.include_usagesends exact token counts in the last streamed chunk, together with its device telemetry. From an older Prism, or any server that sends nousage, BenchRig estimates the prompt tokens (word count x 1.3) and counts streamed chunks as generated tokens; such results are markedusage_estimatedand the reports say so, because prefill and decode speeds then depend on the guess. - Prism holds one model at a time and has no unload. When a model is still loaded as the next one is benchmarked, the "model memory" figure is left out
(
vram_baseline_dirty), because peak minus a baseline that contains the previous model would be too small. Restartprism servebetween models for it.
GPU memory on long prompts
ONNX Runtime GenAI's GPU memory grows with the prompt length (about 1.4 MB per token for Phi-4-mini) and is not released afterwards, so
the context suite's large steps drive Prism's peak memory up (10.6 GB of model memory in the comparison against 3.8 GB on Ollama), which can
trip the memory warning and its composite-score penalty. Starting Prism with PRISM_PREFILL_CHUNK=256 bounds it (6.6 GB instead of
11.7 GB at 4500 prompt tokens for Phi-4-mini), but the cost differs by model: on two other models the peak fell by 54% and 5% while time to first
token rose by 110% and 33% (see the Prism docs). It is off by
default; benchmark with and without it if memory matters to your comparison, and note which one you used.
Which device ran it
Each result record from Prism carries a device field (cuda or cpu): the execution provider Prism reports for that request, from
the response's telemetry or, for streamed responses, from /health. If Prism reports nothing the field is omitted; treat a
missing value as unknown, not as GPU.
Model names do not tell you the device
With Prism's default --device auto, ONNX models are run on the CUDA execution provider when it is available, including
models whose name says generic-cpu. Measured with qwen3-0.6b-generic-cpu-4:v4 on an RTX GPU under WSL2: --device auto
used the GPU (about 1.4 GB more GPU memory, 33% utilisation) and reported cuda; --device cpu left GPU memory untouched
and reported cpu. For this 0.6B model the CPU run was faster (about 57 vs 24 tokens/s), so the choice can change a
comparison. Start prism serve with an explicit --device cuda or --device cpu when the result depends on it, and read the
device field rather than the model name.