witcheer/rtx-5090-benchmarks
RTX 5090 LLM Benchmarks Speed and quality benchmarks for quantized LLMs on NVIDIA RTX 5090 32GB, measured with llm-bench-rig. Quality Benchmarks Generative evaluation through llama-server chat completions. Replicates standard benchmark methodology using custom evaluators — no lm-evaluation-harness dependency. Results are split by reasoning mode: comparing a thinking-on (reasoning) model's quality against a thinking-off model is apples-to-oranges, so the two groups… See the full description on the dataset page: https://huggingface.co/datasets/witcheer/rtx-5090-benchmarks.
RTX 5090 LLM Benchmarks
Speed and quality benchmarks for quantized LLMs on NVIDIA RTX 5090 32GB, measured with llm-bench-rig.
Quality Benchmarks
Generative evaluation through llama-server chat completions. Replicates standard benchmark methodology using custom evaluators — no lm-evaluation-harness dependency.
Results are split by reasoning mode: comparing a thinking-on (reasoning) model's quality against a thinking-off model is apples-to-oranges, so the two groups are ranked separately. q_avg is the mean of the five tasks.
Thinking OFF (non-reasoning · direct answer)
† North-Mini-Code-1.0 is a reasoning model, run think-OFF for board parity. ARC-Challenge is reasoning-gated: 60.2 think-OFF to ~95 think-ON (+35), which deflates its q_avg. See the report.
² Re-banked 2026-07-15 under the pinned harness (rig ec00ff0, llama-server b9653); the re-bank moved HumanEval by one passing problem (92.7 → 93.3) and nothing else beyond 0.05. ³ unsloth compressed-tensors NVFP4 (23.4GB, 303 modules kept high-precision, lmhead dequanted), served via vLLM 0.21.0 on the native cutlass sm120 FP4 path, measured 2026-07-15 under the same pin. Protocol and per-suite deltas: report addendum. ⁴ NVFP4-GGUF (s-batman MTP GGUF, 14.6GB, flat quant), llama.cpp b9365 BLACKWELL_NATIVE_FP4, June numbers, pre-pin: NVFP4 vs Q6_K. Rows ³ and ⁴ share a format name and nothing else; the 0.9 qavg spread between them is recipe coverage (which modules stay high-precision), not the FP4 format. ⁵ QuantTrio true AWQ (4-bit g128 gemm, 8 modules ignored — flat recipe, 21.9GB), served via vLLM 0.21.0 awqmarlin, measured 2026-07-16 under the same pin. sglang 0.5.14 cannot serve this artifact (hybrid-GDN dtype wall: degenerate output at bf16, crash at fp16) — report. The recipe-coverage rule now holds cross-format: flat recipes cluster (⁴ 93.2, ⁵ 93.1) while the protected recipe (³) holds the baseline.
⁶ 127.5B-total / 5.1B-active hybrid MoE (bailingmoe3), run 2026-08-08/09 on the open llama.cpp PR #26608 branch (head 0266ebca6) — upstream support had not merged at run time. All 512 routed experts in system RAM (--n-cpu-moe 99): Q3KM 46.0 tok/s tg128 at 3.8GB VRAM peak (report). Three-quant ladder measured 2026-08-09 under the identical harness: IQ3XXS 39.6 tok/s ([report](reports/ling-3-0-flash-iq3-xxs.md)), IQ2M 45.6 tok/s (report) — decode speed is non-monotonic across the ladder (IQ3 dequant cost), prefill scales with file size. Companion: `--n-cpu-moe` offload-curve sweep (peak 66 tok/s at 27.5GiB VRAM; the optimum sits ~4GiB below the 32GB ceiling).
⁷ EschaLabs eschamoe 2-bit (12.3GB: 2/3-bit experts, int8 dense), served via the vendor's closed-source escha-sglang runtime (their published 5090 recipe, THINK=0) — the only non-open serving stack on this board, flagged accordingly. Same five-task harness over the server's OpenAI-compatible /v1; 285.7 tok/s single-stream decode measured (vendor claim 283, confirmed). Same base model as the UD-Q4KM row two lines up: the 2-bit build gives up 0.9 q_avg (concentrated in HumanEval, −2.4) for a 40% smaller file that also fits 16GB cards. Report.
⁸ Official NVIDIA NVFP4 release build (21.6GB), served via vLLM 0.25.1 on the native cutlass sm120 FP4 path, measured 2026-08-11 same-day with the Q4KM row below it. First board pair where the vendor's own FP4 recipe is compared against a community Q4 GGUF of the same model on identical harness: quality is a wash (+0.4 qavg, all per-task deltas ≤1.4), and NVFP4 decodes in the same speed class or slightly ahead (410.5 tok/s chat-server median vs 377.4 tg128 — different conventions, see the report for both legs and the sm_120 reproduction traps).
⁹ Six-rung GGUF quant-tax ladder (bartowski imatrix repo), measured 2026-08-12/13, llama.cpp b10338 worktree, all rungs fully VRAM-resident. The tax is nearly zero above the floor: Q5KM to IQ2M spans 0.4 qavg while decode climbs 349 → 399 tok/s and VRAM drops 25.2 → 17.7 GiB. Only IQ2XXS pays (−1.7 qavg vs IQ2M), and the entire drop is HellaSwag. IQ2M strictly dominates Q3KM and IQ4XS (smaller, higher qavg, faster). Ladder GGUFs embed the MTP drafter head (inert here). Ladder report.
¹⁰ Seven-rung GGUF quant-tax ladder (unsloth day-0 repo, UD = dynamic imatrix recipe), measured 2026-08-14/15, llama.cpp b9653, all rungs fully VRAM-resident. No cliff anywhere: Q80 to UD-IQ2XXS spans 2.9 qavg over a 3.4x file-size range, Q6K ties Q80 to the second decimal (93.66 both), and UD-IQ3XXS holds 92.7 from an 11.1GB file (12.8 GiB peak — 16GB-card territory) at 96 tok/s. MMLU pays most of the tax; the IQ2 rungs pinch HumanEval first. The tightness is short-context only: on long-context retrieve-and-use (15 tasks per depth at 16k/32k/64k, measured 2026-08-16) Q6K is perfect at every depth while UD-IQ3XXS holds 73/67/80 — the 1.0 q_avg gap becomes ~27 points under depth load. And it is a benchmark-ceiling artifact too: on GPQA-diamond (standing second-tier metric since 2026-08-17) the same seven rungs spread 11.1 points where the board spreads 2.9 — the 4-bit band ties the top at 49-50.5 while the IQ2 rungs fall to 39-43. Ladder report + both addenda.
¹¹ NVFP4 checkpoint (unsloth day-0 cut, 22.6GB) served by vLLM 0.25.1 on sm120, measured 2026-08-17 — the only non-llama.cpp Qwen3.8 row; quality same-harness over HTTP, cross-stack for speed. Q6K-sized but lands below Q4KM, HumanEval pays nearly the whole tax (89.6 vs 94.5). The lane's draw is the shipped MTP speculative head, which llama.cpp cannot run yet: 1.72–1.81x decode at every prompt depth tested (69 → 114–125 tok/s effective, held at 32k). NVFP4 report.
¹² Full-precision BF16 reference (split GGUF, 54.7GB — 1.7x the card), quality-only via llama.cpp partial offload (-ngl 40), banked 2026-08-17→20 across three overnight windows. Lands mid-ladder at 93.5 (ties UD-Q4KXL, 0.1 under the Q6K/Q80 pair) with GPQA-diamond 48.5 inside the 4-bit band's noise band — the ladder's 4-bit-and-up rungs were already at the full-precision ceiling, and the IQ2 floor's loss is now measured against a true reference. No speed rows by design (partial-offload decode is not comparable to resident rungs). BF16 addendum.
¹³ Ornith 1.5 35B-A3B (MoE, ~3B active), a reasoning model run think-off for board parity, measured 2026-08-21. Q4KM is the vendor's first-party GGUF (20.2GB, llama.cpp b9653, 21.4 GiB resident, 303 tok/s tg128); NVFP4 (23.4GB) served via vLLM 0.25.1 on sm120 at ~300 tok/s chat-server decode — the two stacks land within 0.1 qavg. The board understates the model twice over: think-off parity, and GPQA-diamond 52.0 think-off / 81.8 think-on (16k budget, 2026-08-22) — level with the dense Qwen3.8-27B rungs in both regimes (50.5 / 79.3-80.8) at 3.8x their decode speed. Shipped MTP speculative head measures negative on vLLM 0.25.1 (245-254 vs ~300 base). Report.
¹⁴ Ornith 1.5 9B (dense hybrid-attention), vendor first-party Q6_K (6.85 GiB, llama.cpp b9653, 188 tok/s tg128), think-off for board parity, measured 2026-08-22→24. GPQA-diamond 41.9 think-off / 74.2 think-on — but the think-on number carries a measured failure mode: 25 of 198 chains (12.6%) never terminate under greedy decoding, at 16k AND 32k budgets, and the vendor's own BF16 GGUF still fails to terminate 22 of the 25 at 32k — the wall is the model under this regime, not the quant (the 35B sibling truncates 14 under the identical recipe). On chains that finish, accuracy is 85%. The 35B-A3B sibling dominates the 9B on every axis on this card, including decode speed (303 vs 188 tok/s). Report.
¹⁵ Qwopus3.8-27B-Flash (Jackrong's fine-tune of Qwen3.8-27B, Q6K with embedded MTP head, 22.4GB), measured 2026-09-07 on llama.cpp b10371 against the banked Q6K base, same harness, same day. Four of five tasks sit within the base's error band; the q_avg is HumanEval alone: 26.8 vs 94.5, because the tune emits exactly one leading space on every code line in 150 of 164 answers, so nesting depth is destroyed in the output and no whitespace repair recovers it (48/164 at best). The model card discloses the indentation issue; this is its size. Think-on GPQA-diamond (16k budget, paired with a same-day base re-run that reproduced the 2026-08-19 result to the item): 70.7 vs 79.3, with the tune spending 4,229 completion tokens per correct answer against 7,740 (2.08x on the 125 items both solve), so the card's efficiency claim is real at about 2x and costs 8.6 points. The card's MTP acceptance advantage does not reproduce think-off (weighted 0.762 vs 0.768, 109 to 145 tok/s for both). Report.
¹⁶ Qwen3.8-Flash-Next (125B total / 10B active MoE, 512 experts, qwen4exp hybrid linear attention), unsloth UD-Q2KXL 78.9GB, does not fit the card: run with the routed experts of the first N layers in system RAM (--n-cpu-moe N, 59 GB RAM), llama.cpp b10853 (fresh master worktree; the arch merged 2026-08-27), measured 2026-09-08/09. Quality legs at N=28 (23.0 GiB): highest MMLU on the board (88.5) and GPQA-diamond 54.0 think-off from a 2-bit cut; GSM8K and HumanEval pay the quant tax. Speed at the ladder optimum N=22 (28.5 GiB): decode 59.7 tok/s tg128, 51.0 at 32k depth, prefill 900 tok/s pp512. The full --n-cpu-moe ladder (44 to 18, nine points) climbs 1 to 2.5 tok/s per 1.8 GiB of experts moved onto the GPU, peaks at N=22, inverts at N=20 (30.3 GiB, 50.2 tok/s) and fails to load at N=18: the optimum leaves ~3.5 GiB free, as on the Ling-3 sweep. Per-card points: 16 GB at N=40 (42 tok/s), 24 GB at N=28 (52.5). On this 59 GB box N=28 sits on the page-cache edge (736k major faults during one depth pass, prefill at depth varying 2.7x between identical runs); N=22 does not. MTP head on the open llama.cpp PR #28243 (at N=28): 1.25x on code and repetitive text, a small loss on prose and chat, because under offload a rejected draft costs most of a plain token. Speed rows are offload-conditioned and not comparable to the resident rows. Report.
Thinking ON (reasoning · extended chain-of-thought)
HumanEval correction (2026-06-04). An earlier harness passed API stop sequences (\ndef,\nclass) that fired mid-reasoning, truncating inline-reasoning models before they emitted code — producing false-low scores (Qwen3-Coder-Next read 10%, not 93%). Every model has since been re-run on the fixed, reasoning-aware harness (no stop sequences,max_tokens=4096, indentation-preserving response handling). A second extraction fix (2026-06-04) makes program assembly format-agnostic — it generates candidate assemblies and keeps whichever one compiles — after Nemotron-3-Nano exposed a case where the model indents only the first body line differently (raw HumanEval read 21%; corrected to 80.5%). Do not cite any HumanEval figure published before this date. Why two tables. Thinking-off rows answer directly; thinking-on rows emit an extended reasoning chain first. The two modes are not comparable on the same axis — including on MCQ/GSM8K — so they are ranked separately. Within a family, turning thinking on trades raw knowledge recall for reasoning depth (compare Qwen3.6-35B-A3B in both tables: MMLU 85.0 → 94.7). ¹ gpt-oss-120B runs via MoE CPU-offload (--n-cpu-moe 20) — it does not fit 32GB VRAM (59GB model); ~30GB VRAM + the rest in system RAM, ~47 tok/s generation. It and the other two thinking-on rows were run on a ~100-item-per-task subset (MMLU 2/subject). ² Muse-Glimmer-30B (Meta, VLM: 28B text decoder + 2B vision encoder; text benches exercise the decoder only) sits in this table because its chat template's reasoning channel has no off switch —reasoning_strength(defaulthigh) modulates depth but every off-looking value (low/minimal/none/off) still produces ~60 reasoning tokens before an MC answer letter. Scored with the standard 50% sampling atreasoning_strength: low; runs fully resident (15.4GB VRAM peak, 85.7 tok/s tg128) on llama.cpp master b10349, the Muse Glimmer merge commit (PR #26841, merged day-0). Full report in `reports/muse-glimmer-30b-ud-q4-k-xl.md`.
Sampling. MMLU & HellaSwag use 50% stratified sampling (seed=42); ARC-Challenge, GSM8K, and HumanEval run the full item counts (HumanEval = all 164). Full per-model reports in `reports/`.
Second tier, thinking on (IFEval · MATH-500 · HumanEval+ · MBPP+)
The five-task boards above are short-answer tasks. This table is the harder second tier, run with thinking on at a fixed budget: max_tokens 16384, ctx 24576, greedy, zero-shot, one pass per item, llama.cpp b9653, 1,583 items per model. Scores are percentages; IFEval is prompt-strict. cap is the share of items whose completion hit the 16k budget: a cell at 10% or more (▲) is a floor, not a ceiling, and is never flat-compared with a low-cap cell. ◆ marks a format miss (answers without \boxed{}). Full per-task counts, capped items, parse failures, tokens per correct answer and median completion length: `second_tier.csv`. Report with the reads and limits: thinking on at a 16k budget · chart.
The top three are a tie: the Wilson 95% half-width on a four-task mean here is 1.6 points. The three ▲ MATH-500 cells spent 12.4k to 12.9k completion tokens per correct answer against 1.8k to 1.9k for the two Qwen3.8 rows; a 32k pass on exactly those three legs is queued and will publish as a separate table. Qwable-27B MBPP+ capped 12.2%. The Qwopus3.8-27B-Flash MATH-500 cell has 325 of 500 answers unboxed at 3.8% capped, a formatting result in the same family as its main-board HumanEval (footnote 15).
Methodology
All benchmarks run at temperature=0. MCQ and GSM8K use max_tokens=2048; HumanEval uses max_tokens=4096 with no stop sequences (reasoning models emit code only after long inline reasoning — premature stops were the bug corrected above). Multiple-choice tasks use generative letter extraction instead of loglikelihood scoring — scores are internally consistent for model comparison but may differ from logprob-based evaluations by 5-15%.
Full per-model reports with MMLU category breakdowns, parse reliability stats, and speed data: `reports/`
Error bars
Every score above is a single greedy pass, so each is a binomial proportion with a sampling interval. `board_ci.csv` publishes a Wilson 95% interval per task per row (from the correct/total counts in each run's detail files) together with the parse-failure count, and a q_avg row whose half-width propagates the five task variances through the mean, treating tasks as independent. Measured across the 47 rows with all five tasks (regenerated 2026-09-10), the median qavg half-width is 0.97 points (the four think-on rows scored on small subsets run 2 to 4 points), and humaneval dominates it in 44 of 47 rows with a median 82% share of the variance, because 164 problems at ~93% pass gives a task half-width of about 4.5 points against under 1 point for the other four. Since 2026-09-10 the file also carries one `gpqathinkon row per think-on GPQA leg (seven rows) with three extra columns, tokenspercorrect, completiontokensmedian, cappedrate`, filled where the leg recorded per-item tokens (legs run since 2026-09-09; the August legs did not record them). The per-budget legs of the [reasoning-budget curve](reports/reasoning-budget-curve.md) live under `results/<slug>-thinkon/budget-<N>/` and are tabulated in that report rather than in this file. Two rows whose qavg differ by less than that half-width are a tie; the tables stay sorted by qavg for continuity, so read neighbouring rows as a band of roughly one point rather than a ranking. Regenerate with `python3 scripts/boardci.py results/`.
Speed Benchmarks
What's measured
- Prompt processing (pp): parallel batched token throughput at context lengths 128, 512, 2048, 4096, 8192, 16384
- Text generation (tg): sequential autoregressive token throughput at 128 tokens
- All models fully GPU-offloaded (ngl=99)
Served (HTTP) lane
The llama-bench numbers above measure the engine on its own. The served lane (scripts/speed_served.py, lib/speed_served.py) measures what a client sees through llama-server's streaming chat-completions endpoint, the path the spec-decode and prompt-cache reports were timed on. Four fixed workloads (prose, code, repetitive, chat; 8 prompts each, lib/workloads.py, the same prompt set those reports used) are sent at temperature 0 with max_tokens=256 after one discarded warm-up request; every request is appended as one json line with the server flag set (mode), cache_prompt, the wall time to the first content chunk, the total wall time, prompt and completion token counts, the server's own timings object when present, and a sha256 of the text so two flag sets can be checked for byte-identical output. Vocabulary: TTFT is the time to the first content token as the reader perceives it (prefill plus queueing); perceived TPS is completion_tokens / (total_s - ttft_s), the rate text arrives at once it starts; total TPS is completion_tokens / total_s, throughput including the wait. Percentiles (p50 and p90 over the 32 requests per pass), not means, are reported, alongside the server's predicted_per_second p50 and, when speculation is on, the acceptance rate sum(draft_n_accepted) / sum(draft_n). A served TPS is not comparable to a tg128 figure from llama-bench: different prompt, different token budget, and the HTTP and tokeniser overhead are inside the served number.
Speed at depth (agent-shaped)
tg128 on an empty context is the number every board quotes and the one an agent loop never sees. Coding harnesses hand the model a 10k to 20k token prompt and then decode against it, so two numbers matter more: how fast the first token arrives on a long prompt, and how much decode speed survives at depth. Both come from the same llama-bench depth sweep (-p 512 -n 128 -d 0,8192,32768, -r 2) that has been a standing leg on every treatment since 2026-08-14 and was backfilled on the resident rows on 2026-09-08/09. `speed_at_depth.csv` carries the raw columns; the table is regenerated with python scripts/depth_table.py table results/.
How to read it: held is tg128 @32k / tg128, the share of decode speed that survives 32k tokens of context. TTFT for a 16k prompt is an estimate, 16384 / pp512 @8k: prefill throughput measured at 8,192 tokens of depth is the closest measured rate for a mid-size prompt, and the true number is a little worse because prefill slows as the prompt grows (compare pp512 @8k with @32k in the csv). When a treatment measured TTFT on the served lane with a real 16k system prompt, that number replaces the estimate and is shown without the tilde. Rows are llama-bench on fully resident models unless a --n-cpu-moe flag is shown; the offload row's prefill is RAM-bandwidth bound and its estimate is cache-state dependent (see the Flash-Next report). Rows without a depth sweep on disk are absent, not zero; the backfill continues through the idle queue.
What your card can run
`card_fit.md` turns the board into a fit table for 8, 12, 16, 24 and 32 GB cards. Each row's VRAM @16k is the peak sampled on the 5090 during the speed sweep (whose largest prompt is 16,384 tokens, so weights + a 16k KV cache + compute buffers), applied as a budget with 768 MiB of headroom: ✅ resident with a 16k context on the board recipe, 🟡 the file fits but the 16k peak does not (shorter context, q80 KV cache, or a smaller quant), ⬜ the file is larger than the card, 🟠 measured with experts in system RAM (the MoE offload rows, which need the RAM as well). Quality (qavg, GPQA-diamond) sits next to each row so the question "what is the best thing a 16 GB card runs" reads off directly. These are 5090 measurements applied to other cards' capacities, not measurements on those cards: peak bytes are the same on any CUDA card at the same context and flags, decode speed is not. Regenerate with python scripts/card_fit.py results/.
Recipes: which llama-server line for this model
`reports/recipes/` answers the question the board does not: given this model on this card, which flags. One page per model, one recommended line at the top, and a six-set table behind it (base, --flash-attn on, KV q8_0, KV q4_0, --parallel 1, MTP draft head), each set served and measured on the four short workloads and on a 16k-token system prompt cold and warm, with VRAM peak and a 40-item GPQA spot check on the KV-quantised sets. Seven pages in (Qwen3.8-27B Q6K, Gemma 4 31B Q40, Qwen3.6-35B-A3B UD-Q5KM, Nemotron 3.5 Lightning Q4KM, Ornith 1.5 35B Q4KM, Qwopus3.8-27B-Flash Q6K, Flash-Next UD-Q2K_XL under offload): flash-attn changes nothing, --parallel 1 is free, q4 KV costs 13 to 29% of decode at 16k depth on all seven, q8 KV is a memory lever on dense models only, and an MTP head pays 1.5 to 2.3x on a 60 to 76 tok/s base but is 0.6 to 0.8x on a 364 tok/s one.
Speed data schema
Key findings
MoE (3B active) vs Dense (27B) on same-family Qwen3.6 models:
- Prompt processing: 2.4x faster across all context lengths
- Text generation: 3.5x faster (271 vs 77 t/s)
- Both degrade ~17% at 16K context (attention + VRAM, not parameter count)
Field Reports
One-shot investigations that don't fit the leaderboard format — claim verification, new-architecture probes, and consumer-hardware autopsies, all measured on the same rig. Newest first.
Related Datasets
- witcheer/agentic-score-leaderboard — model-agnostic agentic tool-calling benchmark (7 models, 40 tasks) + the SWE-bench reality anchor
- witcheer/sovereign-asr-bench — local ASR on the 5090: Parakeet-TDT vs Whisper (WER / RTFx / VRAM)
Hardware
Tooling
All benchmarks generated with llm-bench-rig — open-source pipeline for speed and quality benchmarks on GGUF and safetensors models.
