This blog has published notes on ten inference engines — llama.cpp, Ollama, vLLM, Sonar (formerly Aphrodite Engine), exo, ExLlamaV3 + TabbyAPI, Strata, PolyStrata, Avalon and Xolotl. This is the decision piece: which of them I would run on the machine I keep being asked about — roughly 100 GB of system RAM and two 16 GB consumer GPUs.
Every figure below I have checked; none is estimated or invented. All are published numbers collected on our benchmark page, https://localai.hex7.com/benchmark.html, which marks every one with a source and dashes where none was found. Self-reported figures are labelled as such, third-party measurements likewise, and where no comparison can be made I say so — that is part of the conclusion, not a hedge.
The engines, and what each one descends from
Five of these projects descend from one another; the lineage matters before any comparison.
- llama.cpp (ggml-org): the general runtime on ggml — GGUF weights, an OpenAI-compatible server (
llama serve), offload flags like--n-gpu-layers. Strata's and PolyStrata's head-to-heads benchmark against it first. - Ollama: wraps that engine — inventivehq describes "the same weights through the Ollama wrapper" — with an MTP draft enabled by default.
- vLLM: contributes the high-concurrency design Sonar inherits: continuous batching, paged KV-cache management.
- Sonar (formerly Aphrodite Engine) is not a successor but the same repository renamed in place: commit "feat!: rename Aphrodite Engine to Sonar", 7 November 2026;
PygmalionAI/aphrodite-engineredirects todphnAI/sonar. Its README: "Sonar is based on vLLM." - exo (exo-explore): a peer-to-peer cluster runtime on MLX — one model across several machines rather than inside one.
- ExLlamaV3 + TabbyAPI: the pair as it ships today. ExLlamaV3 is MIT-licensed, at v1.6.6 (31 Oct 2026); TabbyAPI is the OpenAI-compatible server that fronts it and has carried only its back-end since 14 July 2026.
- Strata (Niko1221): uses llama.cpp's raw materials — GGUF files, quantisation formats, the ggml kernel lineage — but is an overfit engine built on those formats, not a branch of its source.
- PolyStrata (simplexai-labs): a fork of Strata running two engines: keeps "the Strata project's, unchanged" for Qwen3.8-Flash-Next, adds its own backends for roughly eleven more models.
- Avalon (freriadoc): a fork of llama.cpp (base merged to 31 October 2026) tuned for one model whose experts live in system RAM it owns.
- Xolotl (Indras-Mirror): a descendant of Strata — its README says "Built from Strata"; the parent's engine merged at 0.1.44.1, over 70,000 lines added on top.
The capabilities table
Before any speed number: what each engine can hold, and where it may put it.
| Engine | Weights it reads | Weights in system RAM? | API surface | Licence | Purpose |
|---|---|---|---|---|---|
| llama.cpp | GGUF (k-/i-quants, MXFP4) | Yes — but OS-paged: layer offload, -cpu-moe | OpenAI-compatible server + UI | MIT | General runtime; thousands of models, every backend |
| Ollama | GGUF through llama.cpp | Same levers, via the wrapper | Its own API; OpenAI-style endpoint | MIT | Appliance: installs with one command |
| vLLM | HF safetensors; GPTQ/INT4/FP8 as tested | No — weights on GPUs; KV paged in VRAM | Its own server | Apache-2.0 | Throughput for many concurrent users |
| Sonar (ex-Aphrodite) | HF-compatible, added formats incl. exl3 | None documented; takes 92% of card VRAM "by design" | OpenAI, Anthropic, Kobold, etc. | AGPL-3.0 | vLLM-line serving, added formats, roleplay samplers |
| exo | HF safetensors through MLX | No — split across machines, not tiers in one | OpenAI Chat/Responses, Claude Messages, Ollama | Apache-2.0 | One model across a machine cluster |
| ExLlamaV3 + TabbyAPI | EXL3 (QTIP) | weights on the card; CPU offload documented for MoE experts only | OpenAI-compatible FastAPI (TabbyAPI) | MIT (ExLlamaV3) / AGPL-3.0 (TabbyAPI) | VRAM-resident generation on one or two cards |
| Strata | GGUF quant formats (IQ-, GSQ-family) | Partly — per-expert VRAM cache; rest read from SSD, not OS paging | OpenAI + Anthropic-compatible | MIT | Desktop appliance for a short list of model families |
| PolyStrata | Strata's engine, plus its own models | Yes — knobs: --ram-experts-mib, hot-expert budget, --lock-experts | Local servers per model; MCP server | MIT | Many large MoEs on an ordinary PC |
| Avalon | Custom IQ3_K/IQ3_KS hybrids stock llama.cpp cannot load | Yes — experts in its own pinned O_DIRECT RAM arena, LRU-managed | OpenAI-compatible on :8080 | MIT | One model pushed far on deliberately old hardware |
| Xolotl | GSQ-family and XQ weights, mixed precision | Yes — three tiers: VRAM, pinned RAM arena by DMA, NVMe | One OpenAI + Anthropic endpoint | MIT | Huge MoEs on one box via heavy RAM + NVMe tiering |
The third column is where this hardware decides: whether an engine owns its weight placement or trusts somebody else's page cache. Sonar and TabbyAPI's AGPL-3.0 also rules them out of stacks that cannot ship AGPL; eight of these licences were checked against LICENSE files in my source notes, and the three general-runtime ones are as their repositories state.
The machine at issue — and what cannot be compared
My rig: about 100 GB of system RAM with two 16 GB consumer GPUs. Up front, honestly: no published benchmark row exists for this exact machine. What exists are runs on boxes adjacent to mine; an argument has to be built from those, and I read them against my budget below. All sources are listed at the end.
What runs on a 2× 16 GB + 100 GB rig — the closest published runs
| Published run — machine as published | Model / weights | Engine | What was published |
|---|---|---|---|
| RTX 4090 + 5700X + 110 GB DDR4 + NVMe, Linux | DeepSeek-V4.1-Flash (552B params) at V4 XQ weights | Xolotl | 32.6 tok/s decode inside agent tasks; 41.1 in fast mode; prefill 258–439 — Xolotl README (self-reported) |
| RTX 5090 D v2, 128 GB (community run) | same family, UD-Q4_XS (136.7 GB) | llama.cpp | 8.6–10.6 tok/s — PolyStrata community file |
| 2 × RTX 4090, EPYC 7443 | Qwen3.8-Flash-Next Q4_0 (93.7 GiB) | llama.cpp | 34.78 → 64.39 tok/s with -cmoe --moe-cache-mib 15000, prompt 440.7 → 321.5 — write-up of llama.cpp PRs #29887/#30112 |
| 2 × TITAN RTX, 125 GiB RAM (community run) | Qwen3.8-Flash-Next IQ3_S | Strata | decode 70.9–77.3, prompt 868.9–1,626.9 at 4K–128K — Strata community file |
| 2 × RTX A4000 | Qwen3.8-Flash-Next, two-stage pipeline | Avalon | prefill of a 19K prompt: 1,079–1,190 → 1,669–1,761 with its pipeline — README (self-reported); untested beyond two GPUs |
| RTX 4070 Laptop 8 GB, 32 GB — smallest card tested | Qwen3.6-35B-A3B UD-Q3_K_M (17.1 GB), same file both engines | PolyStrata vs llama.cpp b11540 | 94–100 write / 1,690 read vs 44.4 (41.5 at 32K) MTP-tuned llama.cpp, prompt 483–494 — PolyStrata's own head-to-head (self-reported) |
| RTX 3060 12 GB + 64 GB; and a 5070 with 64 GB (community runs) | Qwen3.8-Flash-Next Q2_0 / DeepSeek-V4.1-Flash | Xolotl | prefill 882–981, decode 39–45 on the 3060; DeepSeek: prefill 121–231, decode 4.7 on the 5070 — Xolotl's WILL_IT_RUN.md |
| RX 7900 XTX + R9700 (two cards), 96 GB DDR4 | Ornith 1.5 122B Q5_K_M (82.6 GiB), same file, 128K context | PolyStrata vs llama.cpp (Vulkan) | a 98K prompt read in 184 s instead of 527 — 2.9×; llama.cpp wrote 13.5 tok/s at 100K — PolyStrata community file |
Read these rows against my budget, not against each other. Closest to mine: Strata's 2 × TITAN RTX community run — a generation above my cards, but a consumer two-card layout with expert caching that works; Avalon's A4000 pair is the only two-card pipeline test published at professional-card scale, though its result is prompt reading, not decode; Xolotl's measured machine is my RAM class plus one card — its README states an 80 GB expert arena on a 110 GB machine, 64 GB on a 90 GB one, so my rig sits between two documented cases, not outside them; PolyStrata goes down to an 8 GB laptop card and advertises multi-GPU on two or three cards, though honestly its largest model (GLM 5.3 Flash, 79–114 GB) "needs a 32 GB card to run at all" — on my box that means the class it demonstrated at laptop scale.
The argument for PolyStrata and Xolotl on this box
The case is not "these engines are faster" as a universal claim — no published head-to-head of PolyStrata against Xolotl exists on any machine, so that comparison cannot be made. The case is narrower: on exactly this budget — one box, two consumer cards, ~100 GB RAM — the published runs and documented memory designs are the ones that fit.
The fix is what separates them on my hardware; three projects discovered the same problem independently. Avalon's README states it: the OS page cache is shared, so any other program pushes experts out mid-token; and the driver limits registered GPU memory to RAM − RAM/64 − 1.5 GiB, so a long prompt on a small machine ends in a crash. Its fix — a pre-registered, LRU-managed O_DIRECT arena inside the engine's own RAM — turns that crash into ~49 tok/s on 16 GB, where the page-cache path reached 13–17 and then crashed. Xolotl states the same tiering as an explicit budget: hot experts in VRAM, tens of gigabytes pinned in RAM read by DMA, the rest on NVMe moved a router layer ahead. PolyStrata landed in the same place: since 0.1.45-poly.7 it stopped holding file parts already on the card (Qwen3.6 after a 32K prompt: 17.9 GiB held → 13.1 GiB, same speed), and its knobs carry numbers — hold 6,144 MiB instead of everything and peak during a 32K prompt drops from 14.0 to 7.3 GiB for a 3–14% write cost; budget the hot-expert set to free RAM minus 4 GiB and first-chat decode rises from 51 to 57–60, after a 24K prompt from 75–78 to 77–85. The lesson all three teach: an engine must own its memory, or the machine takes it back mid-token.
The table above shows this pattern landing on boxes like mine — Strata's two-card row, Xolotl's Gauntlet rows, PolyStrata at laptop scale, the two-AMD-cards prompt test. Where unowned paging falls out is just as published: the tuned llama.cpp row reaches 64.39 but loses prompt speed doing it, and its community row at 8.6–10.6 tok/s shows what a 136.7 GB file costs at my model class. The starkest pair on the benchmark page is Strata's head-to-head on a 12 GB RTX 3060 with 46 GB RAM: llama.cpp tuned with -ngl 99 -ncmoe manages 9.1–9.8 decode and 294–338 prompt; Strata, in the same run on the same file, publishes 41.6–41.9 and 910–1,050 — published by the Strata team, though it names llama.cpp's numbers.
So for this machine I would run PolyStrata (its knobs match my RAM budget, its multi-card support exists, and its smallest published runs need less than I have) or Xolotl (measured on my RAM class with one card more; its tiering documentation states my RAM case). Both descend from Strata — PolyStrata is a fork of it running two engines; Xolotl says "Built from Strata" — and their caveats are honest: Xolotl is research code from one developer, Linux-first (its Windows path exists only for the DeepSeek model); PolyStrata marks its own extra backends experimental. Neither claim is universal; on other hardware the answer flips.
Where the other engines are the right answer instead
High-concurrency serving on data-centre cards: vLLM and Sonar
If the box has H-class memory and many concurrent users, these are the answer. The measured H100 row (by the hosting company) puts vLLM at 120 tok/s at one request, 650 at ten, 1,850 at fifty, 2,400 at one hundred, first token 380 ms at fifty; on eight GB200 vLLM reports 26.2K prefill and 10.1K decode TPGS (their metric: tokens per GPU per second), and 7,360 tokens/GPU/s single-GPU prefill on a GB300/B300. Sonar's tuned four-RTX-PRO-6000 run (self-reported) reaches aggregate decode 428.3 → 1,083.3 tok/s at C=8 with DSpark speculation over a 2,674-token prompt — and the only published Sonar-vs-vLLM row on an H100 is modelled estimates by the publisher (48 / 380 / 1,450), not measurements of Sonar. On two consumer cards its docs advise care: no NVLink domain, 92% of the card "by design"; nothing in its pages tiers weights into system RAM, so my 100 GB buys Sonar nothing.
An OpenAI-compatible box that works out of the installation command: Ollama
The simplest case — one command installed, clients pointed at an OpenAI-style endpoint — is what Ollama is for; it inherits llama.cpp's offload levers. The rows show where it stands under the wrapper: same weights on a rented 5090, llama.cpp generated 249 tok/s with 83 ms to first token, Ollama 108 with 221 ms; on older desktop and M3 Max rows llama.cpp led again, 77.0 vs 69.1 and 53.5 vs 46.2. The one case it beats bare llama.cpp is its default MTP draft: 39.9 → 76.2 (L40S: 57.3; RTX 5090: 129.7). Use it when the wrapper, not the benchmark, is what you need.
VRAM-resident EXL3 weights for single-card fast generation: ExLlamaV3 + TabbyAPI
The project's earlier weights format has a run table published by its own maintainers (measured only against their first release — there is no comparison with other engines) and those numbers are the fastest thing on record for this family: 211 tok/s on Llama-2-7B at 4.0 bpw, 50 on CodeLlama-34B at 4.0 bpw, 38 on Llama-2-70B at 2.5 bpw, on the named 3090 Ti and 4090. ExLlamaV3 publishes no equivalent table, so its speed case rests on those earlier measurements; what V3 does document is CPU offloading for MoE experts, which changes what a two-card box can hold. For one card where the weights fit, hard to beat — but no EXL3-versus-GGUF comparison is published anywhere I could find.
A cluster of separate machines rather than one box: exo
If the memory ceiling need not be one machine's, exo is the answer: four M3 Ultra Mac Studios with 1.5 TB combined, measured by a journalist (Geerling), ran Qwen3-235B at about 32 tok/s and Kimi K2 Thinking around 30, with RDMA cutting memory-access latency from ~300 µs to under 50 — while llama.cpp's RPC layer-spreading got slower as nodes were added (no number published). On my rig exo is not a deployment today: Linux is CPU-only, and Mac nodes refuse to join Linux nodes.
The general runtime, and the older siblings
llama.cpp stays right when "whichever model shipped this week" matters, or when tuned flags make a big MoE run at all — 64.39 tok/s with -cmoe on two 4090s is llama.cpp. Strata and Avalon remain right for single-card desktops, but scope themselves to one model family; PolyStrata and Xolotl are what their authors built when they wanted more.
Where no comparison exists
For honesty's sake: I found no published figure for Sonar on any consumer two-card box; none for exo on NVIDIA hardware under Linux; no head-to-head between PolyStrata and Xolotl on any machine; no EXL3-versus-GGUF test in either direction; and no number for llama.cpp's RPC spread, only a report that it got slower. A benchmark page full of dashes is data too.
How I verified this
The figures above were gathered while compiling https://localai.hex7.com/benchmark.html, which marks each number with a source and states which machine it ran on. The sources collected there: Strata's README, its bench/results/2026-10-06-llamacpp-0.6.0 head-to-head and community-benchmarks files; PolyStrata's README, its 2026-10-11-laptop-qwen36-llamacpp-b11540 head-to-head and COMMUNITY_BENCHMARKS file; Avalon's README tables (its runs against Strata v0.2.9 on the same boxes); Xolotl's README Gauntlet v3 table and speed log plus WILL_IT_RUN.md; the run table the ExLlama maintainers published for their earlier weights format; computingforgeeks' three-way test on rented cards; atomic.chat's Ollama-vs-llama.cpp on an RTX 5090; inventivehq's rows; developersdigest's write-up of llama.cpp PRs #29887 and #30112; Jeff Geerling's four-Mac-Studio exo test; dphnAI's Sonar measurement on four RTX PRO 6000; Spheron's measured vLLM H100 rows and its explicitly-modelled Aphrodite estimates; vLLM's own GB200/GB300 blog posts. This blog's engine notes record each project's own claims in detail. The one thing I could not verify is the machine at the centre of this article: two 16 GB cards with ~100 GB of RAM never ran in any published test. Mine will, and when it does I will publish those rows under the same rules as everyone else's.
