← Steppe Integrations / Articles

What Consumer Hardware Actually Does

Twenty-nine local-model labs, May to August 2026, across three consumer GPUs: an RTX 4070 Ti, an RTX 5070, and a pair of Intel Arc Pro B70s. Every number below is measured, dated, and attributed to the lab that produced it.

Sixty-four gigabytes of VRAM for near or less than the price of one flagship card is a trade almost nobody writes up. Here is what it actually returns, where it stops, and the one constraint that turns out to matter more than any of it.

Six things this hardware buys you

Each tile is a claim with a measured number behind it. Follow it to the lab that produced it.

Run large models fast 86.9 tok/s A 30B mixture-of-experts on a single card. The placement ladder → Run models that shouldn't fit 63 GB resident A 120B served from two cards at 26–29 tok/s. The resident 120B → Change weights, not just serve them 2.96 → 1.13 A LoRA fine-tune trained on an Intel GPU, re-served in six seconds. Training on it → Win by configuration One flag took a 70B from unusable to usable. What the flags are worth → Match cloud quality at zero marginal cost 93.8 vs 90.6 Local outscored a frontier model on a graded task. Local vs cloud → Know what actually breaks 32 GB System RAM binds long before VRAM does. Where it stops →

Generation speed, single stream

Tokens per second at shallow context, by model and rig. Longer is faster. Measured May–July 2026.

Qwen3-30B-A3Bone B70, Linux86.9
Qwen3-30B-A3Btwo B70, Windows81.7
Qwen2.5-14BRTX 5070, CUDA59.9
gpt-oss-120btwo B70, Linux27.7
Qwen2.5-32Bone B70, Windows23.7
Llama-3.3-70Btwo B70, Windows11.3
Mixtral 8x22BRTX 5070 + system RAM4.2

All figures Q4-class quantization except the 120B (MXFP4) and the Mixtral (Q2_K). The two eras are not directly comparable — see the note below. Full tables in each section.

Two rows are worth pausing on. The Mixtral is a 140-billion-parameter sparse model, 52 GB on disk, running on a workstation with a 12 GB card — 128 GB of system memory does the carrying while the GPU contributes a slice, roughly 81% CPU to 19% GPU. Four tokens a second is useless for chat and perfectly adequate for an overnight reviewer that reads a diff while you sleep. And the 70B only appears on this chart at all because of a single configuration flag; without it, that row reads 21.5 tok/s of prompt processing instead of 151.4.

How the rig got here

None of this was bought as a lab. It accreted, one constraint at a time, and the sequence explains most of the numbers below — including the one that keeps breaking.

The hardware lineage. Each step was a purchase decision, not a plan.
StepThe machineWhat it unlocked
1A Ryzen daily driver on Windows 10 with an RTX 4070 Ti, 32 GB DDR4First local models, on Ollama. The planner-and-critic experiments in section 1 ran here.
2Same box, two Intel Arc Pro B70s go inBought at MSRP, which is the entire reason this configuration exists. 64 GB of VRAM on a machine with 32 GB of system RAM — the inversion behind finding 1.
3An open-box workstation, 128 GB DDR5 + RTX 5070, becomes the daily driverFrees the first box from having to be anyone's desktop. Also the rig for every 12 GB NVIDIA measurement in section 1.
4The B70 box converts to native LinuxOnly possible once it wasn't the daily driver. Unlocked Intel's Battlematrix multi-GPU stack — and everything in section 3.
5Pending: B70s move to the 128 GB DDR5 machineThe obvious fix for the memory inversion. Blocked on a motherboard that will take both cards properly.

Step 2 is the whole story of this hardware in one line: two large GPUs bolted onto a machine whose system memory was specified for a single one. That mismatch is not a footnote — it is the binding constraint in three separate labs, and it is why the most useful finding here is about DDR4 rather than VRAM. Step 5 is the fix, and it hasn't happened yet.

Two eras, one box. Step 4 splits the record in half. The dual-B70 machine was benchmarked first on Windows 10 + Vulkan (May–June 2026), then on native Ubuntu + SYCL / Level Zero from late June. The harnesses differ, so throughput does not carry across the migration — treat them as two platforms. Exactly one measurement is clean across both, and it is in section 3.

Six findings that survived every lab

1. System RAM is the binding constraint, not VRAM

This is the one that costs newcomers the most time. The B70 box has 64 GB of VRAM and 32 GB of DDR4, and the 32 GB is what breaks — repeatedly, in three independent labs. A stack sweep found the box sitting at 24 GiB used with one 30B model resident and swap 100% saturated. A judging run OOM-killed until the critic model's context came down from 32k to 8k, which freed about 7 GiB. And on 30 July three large models enabled at once produced 81 crash-loop restarts and roughly 18 GiB of memory that went missing entirely — trapped by killed driver allocations, and only recoverable by rebooting.

If you are speccing a local-inference box: buy the system RAM. The VRAM number on the box is not the number that will stop you.

2. MoE is the architecture that fits consumer hardware

At equal size — roughly 32B total parameters, Q4, one card — a 3B-active mixture-of-experts decoded 5.7× faster than a dense 32B (130 vs 23 tok/s) and prefilled 2.9× faster. Decode streams only the active parameters, so sparsity buys back exactly the memory bandwidth consumer cards don't have. Every practical result in this whole corpus rests on that.

3. Backend and kernel choice swing results more than the GPU does

Same model, same card, same prompt: CUDA processed the prompt at 2276 tok/s and Vulkan at 68.5. A 33× spread on identical silicon. And on Vulkan / Arc, flash attention turns out to be a pessimization — about 4× slower than the default attention path at depth. Since quantized KV cache forces flash attention on, "save memory with q8 KV" is a trap on that stack: it measured 2–4× slower, not faster. That one began as a wrong prediction and had to be corrected against the data — which is how it became a finding rather than an assumption.

The most extreme case is a single flag. Running a 70B across both B70s, turning memory-mapping off took prompt processing from 21.5 to 151.4 tok/s — a 7× win, and the difference between "unusable" and "usable". Nothing about the hardware changed. If you are benchmarking a local stack and the number looks absurd, suspect the configuration before the card.

4. Context depth is the real cliff, not model size

A 30B MoE that fits comfortably on one B70 decodes at 86.9 tok/s empty and 5.3 tok/s at 64k context. On the Windows/Vulkan side the same shape showed 132.8 tok/s empty falling to 11.5 at 64k — roughly linear to 32k, then a superlinear cliff. Meanwhile prompt ingest dominates the wall clock: a 57,000-token request spent 207 of its 213 seconds just reading the prompt.

Which means the thing worth engineering is not placement. It's caching. An identical 8k prompt sent twice went from 11.8 s to 0.17 s — 68× — on cache hit. And restoring a saved KV cache beat re-computing it by 29× on real bytes, with the advantage growing with context: 22× at 1k, 75× at 14k.

5. Local output held up against frontier cloud

On a scored documentation and decision-record task, the local 120B model scored 93.8 against Gemini 3.1 Pro's 90.6 and 3.5 Flash's 89.2. The cloud's measurable advantage was latency — about 4–5× faster — and that was the entire advantage. One task family, fifteen cells — not a claim that local wins everywhere. The narrower claim: "local is the cheap option you settle for" did not survive contact with a rubric.

6. And you can train on it, not just serve

The one most likely to be assumed impossible. A LoRA fine-tune of a 7B coder model, running on one Arc Pro B70 on Windows via PyTorch's XPU backend, took held-out loss from 2.96 to 1.13 in 108 seconds of training — then merged, quantized, and served on the same card in about six seconds, generating correct code. Full detail in section 4. Local inference is well-trodden ground by now. Local weight-changing, on a non-NVIDIA consumer card, is not.

All sections

1 · NVIDIA consumer — RTX 5070 and 4070 Ti, 12 GB each

Rig: HP OMEN 45L · Intel Core Ultra 9 285K (24 threads) · 128 GB DDR5 · RTX 5070 12 GB GDDR7 · Intel iGPU · Intel AI Boost NPU · Windows. The 5070 labs: 2 July 2026. A separate round on an RTX 4070 Ti 12 GB GDDR6X ran from June.

Backend lab — CUDA vs Vulkan vs the integrated GPU

The same model and prompt driven through four isolated servers on separate ports, to find out what the backend choice alone is worth.

Qwen2.5-14B, 4096 context, 957 prompt tokens, 120 output tokens. Measured 2 July 2026.
BackendDevice pathLoadPrompt evalOutput
CUDARTX 50703.11 s2276.17 tok/s59.88 tok/s
VulkanRTX 507011.11 s68.51 tok/s42.26 tok/s
Vulkan, mixedRTX + Intel visible9.13 s1921.88 tok/s45.32 tok/s
VulkanIntel integrated GPU12.35 s47.90 tok/s3.70 tok/s

Source: Ollama backend lab — results summary, raw CSV, per-profile JSON and runner logs. 2 July 2026.

The 52 GB sparse model, off system RAM

Mixtral 8x22B Instruct Q2_K (140.6B total params, 52 GB) on RTX 5070 + 128 GB DDR5. Measured 2 July 2026.
ContextPrompt tokensPrompt evalOutputResident
8,1926,875224.79 tok/s4.12 tok/s~53–56 GB
16,38414,425243.91 tok/s3.77 tok/s56 GB
32,76828,770205.41 tok/s2.27 tok/s60 GB

Cold load 39.6 s, warm load 0.03 s — residency is the whole cost. The machine stayed responsive throughout and never obviously paged.

Source: local MoE findings note. 2 July 2026.

The capability matrix and the baseline protocol

Two more documents from the same day turn those numbers into decisions rather than trivia. A capability matrix assigns each model class an operational role — resident controller, interactive specialist, batch specialist, fallback worker, overnight critic — and tags every cell measured, published, or inferred, so you can see which claims came off this rig and which came off a model card. Its operating conclusion: a 12 GB GPU strongly favours a control-plane and specialist split, and the constraint is residency, not active parameters. A 30B MoE behaves like a small model per token, but its total weights still drive placement.

The other is a dated baseline snapshot plus a written rerun protocol, built deliberately so a future Arc Pro B70 rerun would be comparable. Warm load for both test models collapses to about 0.10 s. Worth noting for anyone building on Ollama: same-service "concurrency" there behaved as queueing against one daemon, not true batched serving.

Sources: hardware capability matrix; RTX 5070 baseline snapshot and baseline protocol. 2 July 2026.

What the raw logs said that the summaries didn't

Going back through the raw per-call CSVs — which log GPU utilization, memory and power draw before and after every request — turned up two things no summary of mine had stated.

Per-call telemetry, CUDA on the RTX 5070. Measured 2 July 2026.
ScenarioModelLoadPrompt tok/sOutput tok/sGPU power
baseline, coldqwen2.5:14b4.52 s1015.6361.828 → 203.4 W
warm, back-to-backqwen2.5:14b0.13 s7154.0462.0030 → 203.8 W
baseline, coldqwen3-coder:30b13.10 s294.3757.4022 → 66.7 W
long prompt @ 8kqwen3-coder:30b10.27 s2154.1250.7921 → 82.7 W

Source: raw capability-bench and cross-service CSVs, RTX 5070. 2 July 2026.

The model matrix — on the 4070 Ti

Worth separating, because it's a different question and a different card. Where the 5070 work is two models deep and many scenarios wide, this one is model-wide: a planner-and-critic loop run across different model pairings to find where it breaks. It broke in three distinct places, each run isolating one.

That question is unresolved — and it is the single best argument for the dual-B70 box that follows: 12 GB forces a choice between a good planner and a good critic, and the choice is what breaks.

Source: local-inference research series and rehearsal run log, RTX 4070 Ti on Ollama/CUDA, from 5 June 2026.

2 · Intel Arc Pro B70 — the Windows / Vulkan era

Rig: 2× Intel Arc Pro B70 (Battlemage Xe2, 32 GB GDDR6 each) · AMD Ryzen 9 5900X · 32 GB DDR4 · Windows 10 Pro · PCIe 4.0 ×8/×8 (the cards are PCIe 5.0 capable; the host limits them). These three repos are public.

b70tools — is Task Manager telling you the truth?

It wasn't. That's why the tool exists. It reconciles four independent telemetry sources — kernel-mode adapter counters, per-process heap budgets, the Vulkan memory-budget extension, and Intel's own power/thermal API — and flags where they disagree in real time.

Measured on the dual-B70 rig, Windows 10, production Intel driver. May 2026.
WorkloadConfigGenerationPromptVRAM/card
Mistral-Small-3.2-24B Q4_K_Msingle card27.3 tok/s~400–443 tok/s14 GB
Qwen3-30B-A3B MoE Q4_K_Mdual split81.7 tok/s30.1 tok/s8.5 GB
Qwen2.5-32B-Instruct Q4_K_Mdual split20.7 tok/s242.2 tok/s9.3 GB

Look at the middle two rows: the 30B MoE generates four times faster than the 32B dense, while the dense model prompts eight times faster. Different bottlenecks, same box.

The other finding was about the cards themselves. They're physically identical and they are not identical in software: the top-slot card runs 10–15 °C hotter under identical load and its telemetry reports physically impossible values — 5.117 V and 8.55 GHz at idle. That's a driver bug, not a hardware one. It took several experiments to conclude the cards deliver identical inference throughput, which is the whole argument for building the observation tool before trusting the dashboard.

That conclusion is not airtight. Four days earlier, the overnight bench below measured the bottom card generating 18% faster than the top one on an identical 14B — 50.09 vs 42.37 tok/s. The later, more careful work concluded they are equivalent. Nothing in the record reconciles the two, so both are reported here rather than only the tidier one.

Source: github.com/djcdevelopment/b70tools — Windows-native telemetry workbench, May 2026. Observation cost: 16.6 MiB RSS, under 130 ms init.

The overnight campaign — 14B, 32B, and a 70B across both cards

A phased ladder run overnight: each card alone on a 14B, then a 32B, then Llama-3.3-70B tensor-split across both, plus a context curve and a KV-precision comparison. About a hundred files of raw output. This is the run the rest of the Windows era was built on.

llama-bench, Q4_K_M throughout, all layers offloaded, dual Arc Pro B70 on Windows Vulkan. Measured 24 May 2026.
ModelPlacementPrompt tok/sGenerate tok/s
Qwen2.5-14Bsingle card (top slot)1261.0642.37
Qwen2.5-14Bsingle card (bottom slot)1335.6850.09
Qwen2.5-32Bsingle card591.8823.69
Llama-3.3-70Bdual, tensor-split, mmap on21.49
Llama-3.3-70Bdual, tensor-split, mmap off151.4111.28

Source: overnight bench campaign, dual Arc Pro B70 on Windows Vulkan, 24 May 2026. Roughly 100 raw JSONL and log files, retained.

denning — treating the KV cache as an OS-managed resource

The deepest lab in the set, and the one to hand a skeptic. The premise: on a box with no GPU fabric, less system RAM than VRAM, and an operating system arbitrating video memory, correct model-state management is bandwidth-roofline admission control — and you have to coexist with an OS memory manager that will act against you. Named for Peter J. Denning's working-set model. Predictions were committed to git before the data that confirmed them.

And the retraction. The two-card symmetric scaling result — a clean 1.96× by replication — is marked provisional and under correction. Driving both cards symmetrically, including the display card, reproducibly trips a Windows display-driver timeout and reset: four resets across two sessions. The concurrency run collected across two of those resets was retracted outright rather than published. The driver reset is the finding: symmetric replication across a display card is catastrophic, not merely degraded.

Source: github.com/djcdevelopment/denning — on-rig validation 19–21 June 2026, dual Arc Pro B70, Windows / Vulkan.

The single-card battery — PCIe width turns out not to matter

After a thermal pull left the box on one card, a six-part battery ran at full PCIe ×16: prefill, model load, session rotation, restore-versus-re-prefill, an engine probe, and a 70B deliberately overcommitted. Predictions were locked to a git tag before the data was collected.

Source: pre-registered single-card ×16 battery, one Arc Pro B70 on Windows, 21 June 2026.

battlemage — where it started

The earliest of the three: single- and dual-card Windows 10 benchmarking, including the dual-card 70B-class run on Vulkan that first proved 64 GB of shared inference was real on these cards. Superseded by the two repos above for anything load-bearing, and worth knowing it exists.

Source: github.com/djcdevelopment/battlemage — from May 2026.

3 · Intel Arc Pro B70 — the Linux / SYCL era

Rig: the same box, migrated to native Ubuntu 26.04 on the modern xe kernel driver with a current Level Zero stack · llama.cpp SYCL build · both B70s · Ryzen 9 5900X · 32 GB DDR4.

Does splitting a model across two cards help? (29 June 2026)

The first Linux-native benchmark asked two things: does multi-card work on Ubuntu the way it didn't on Windows, and is splitting actually better than using one card?

Qwen3-30B-A3B Instruct Q4_K_M, KV cache q8_0, all layers offloaded. "single" = one card; "layer" = both cards, split 1:1. Measured 29 June 2026.
Context depthsingle — promptsingle — generatelayer — promptlayer — generate
0 (empty)1205.8586.921146.0184.30
8,192612.1229.12607.2328.64
16,384405.4417.65405.7317.48
32,768241.369.91240.649.86
65,536132.315.28130.714.89
131,072timed out — no throughput inside a 420-second budget

Multi-card layer split works, and buys nothing for a single stream. Parity through 32k, slightly worse at 64k. The second card is capacity, not speed. The more aggressive split modes weren't even candidates: row-split segfaulted on both variants, and tensor-split timed out and then segfaulted.

Source: SYCL context-ladder lab, dual Arc Pro B70 on Ubuntu, 29 June 2026.

The same question through a real server

Benchmarks measure the model. This measured what a client experiences — a resident server at 128k context behind an OpenAI-compatible facade, timing readiness, time-to-first-token, streaming and cache reuse.

Single-card placement, one slot, 32-token generation cap. Measured 29 June 2026.
Prompt tokensTotal requestPrompt tok/sGenerate tok/sTime to first token
7,2089.8 s863.4922.441.03 s
14,34223.4 s671.7215.741.66 s
28,65166.0 s456.649.922.91 s
57,228213.3 s275.695.695.43 s

Then the concurrency ladder, at about 14,300 prompt tokens: 1 client 22.9 s, 2 clients 45.3 s, 4 clients 91.0 s, 8 clients 181.5 s. Almost perfectly linear — which is the bad news. Time-to-first-token is nearly identical to full completion time at 1 through 4 clients, meaning streaming stops being useful the moment concurrent prompt ingest dominates. The conclusion there is architectural, not hardware: what needs work is request scheduling, prompt-cache strategy and admission control.

Source: service-path placement matrix, depth ladder and concurrency ladder, 29 June 2026.

What the two cards can actually say to each other (18 July 2026)

Remember the 6.48 GB/s host-bounced number from Windows. On Linux, with the modern driver and Level Zero stack, the peer-transfer benchmark was built from source and run — 50 iterations, 8 bytes to 256 MB.

Peer-to-peer transfer between the two Arc Pro B70s, Ubuntu. Measured 18 July 2026.
ModeOperationBandwidth at 256 MBLatency floor at 8 B
UnidirectionalWrite14.29 GB/s6.17 µs
UnidirectionalRead13.06 GB/s7.75 µs
Bidirectional (aggregate)Write16.61 GB/s5.07 µs
Bidirectional (aggregate)Read20.92 GB/s6.67 µs
Dedicated copy engineWrite14.29 GB/s

14.29 GB/s is the practical ceiling of PCIe 4.0 ×8. Going through the root complex costs nothing. That is the same traffic that was host-bounced at 6.48 GB/s on Windows — and it is the single cleanest measurement of what the Linux migration was worth on this hardware. Transfers are perfectly symmetric in both directions, and the dedicated copy engine matches the compute engine exactly, so bulk weight and cache movement can ride the blitter without stealing compute.

Source: peer-transfer microbenchmark, dual Arc Pro B70 on Ubuntu, 18 July 2026.

A 63 GB model, resident, on two consumer cards (18 July 2026)

The question was whether a 120-billion-parameter MoE — 63.4 GB in a single file — can be an always-warm service on hardware like this.

gpt-oss-120b MXFP4 on dual Arc Pro B70, layer-split, four serving slots. Measured 18 July 2026.
MetricValue
Cold load to health-OK~3.2 min
Warm prefill221.6 tok/s
Decode, single stream26.6–28.7 tok/s
Concurrent decode, 4 slots~31 tok/s aggregate
Host RAM, steady state12 GiB used / 18 GiB available
Service restarts across the soak0

It fits only because about four layers of experts ride host memory rather than VRAM — that flag is required, not tuning, since 63.4 GB of weights exceed roughly 60 GiB of usable VRAM. Sparse architecture plus a little CPU offload is the whole trick.

Then the attempt to break it

The brief was blunt: find out if it breaks before we build things with it. Six sweeps — concurrency ladder, context depth, decode-heavy, sustained soak, overload burst, and memory pressure. 453 requests, 453 successes, zero restarts.

The one real trap: over-limit prompts truncate silently. A deliberate 17,500-token request against a 16,000-token slot ceiling did not error. It returned success, normal time-to-first-token, normal decode — the server had quietly truncated the prompt to fit. Context loss with no signal to the caller. If you build on a local inference server, enforce payload size yourself. It will not refuse for you.

Source: stress characterization of the resident 120B model, 18 July 2026. Instruments and raw per-request data retained so the campaign is rerunnable after any config change.

The standoff, 30 July 2026

Not a planned benchmark — an incident, and the most instructive record here for anyone about to run several local models at once. Three large models were all enabled as boot-persistent services on one box. They starved each other.

Fixed by making the services mutually exclusive at the init-system level, adding start-rate limits and alerting. The eventual topology decision cut the other two models entirely: one model serves every role.

Source: incident trace, dual Arc Pro B70 on Ubuntu, 30 July 2026.

4 · Training on it — LoRA fine-tuning on an Intel card

Rig: one Intel Arc Pro B70, 32 GB · native Windows · PyTorch 2.12.1 with the XPU backend · base model Qwen2.5-Coder-7B. 22 June 2026.

Everything above is about serving models. llama.cpp serves a model; it cannot change one. This is the other half — and it is widely assumed to be unavailable on this hardware.

It got found by accident. A probe meant to assess a different inference engine refuted its own premise: the environment already had PyTorch's XPU build working on native Windows. Not WSL, not a container — native. torch.xpu saw the B70, and matrix multiply ran at 150 TFLOPS fp16 and 158 TFLOPS bf16, with the matrix engines engaged and bf16 available — a numeric format the Vulkan serving path doesn't have. The engine under test was blocked on Windows by packaging, not by any absence of hardware support. That reframed the whole question and opened the door to training.

The memory ceiling, mapped before trusting it

Before any real run, peak VRAM was swept against sequence length, batch size and gradient checkpointing — to find the envelope deliberately rather than discover it by crashing.

bf16 LoRA, rank 16, all linear layers, on a 7B base. One Arc Pro B70, 32 GB. Measured 22 June 2026.
Sequence · batch · gradient checkpointingPeak VRAMResult
1024 · 1 · off30.3 GiBfits, barely
2048 · 1 · off~45 GiBout of memory
4096 · 1 · off~43 GiBout of memory
2048 · 4 · off~40 GiBout of memory
4096 · 1 · ON27.3 GiBthe working envelope
8192 · 1 · on~37 GiBout of memory

Gradient checkpointing isn't a tuning knob here, it's a requirement. Without it the 7B runs out of memory by a 2048-token sequence. With it, 4096 tokens at batch size 1 fits in 27.3 GiB with room to spare. Past that you need 4-bit quantized training. Note also that the over-budget runs didn't fail cleanly — they climbed past 32 GiB by spilling into shared system RAM first, the same OS demotion behaviour that haunts the serving side.

The actual fine-tune, and closing the loop

Then a real run inside that envelope: 40.4 million trainable parameters — 0.53% of the model — held-out loss 2.96 to 1.13, training loss 2.33 to 0.91, peak 17.0 GiB, sixty optimizer updates in 108 seconds, producing a 157 MB adapter.

Then the part that makes it a loop rather than a demo. Merge the adapter into the base weights, convert to the serving format (14.2 GB at half precision), quantize to 4-bit (4.36 GB), and hand it to the ordinary Vulkan serving path. It loaded in about six seconds and generated a correct Fibonacci function.

Train on one backend, serve on another, same card. The fine-tuned model re-enters the existing serving path unchanged — nothing downstream needed to know it had been modified. That's the whole proposition: a consumer Intel GPU that can both change a model's weights and then serve the result, on Windows, without a datacenter or a cloud bill.

Two honest limits. This is LoRA, not full fine-tuning — half a percent of the parameters, not all of them. And a 7B is a small model; 14B and up, or longer sequences, need 4-bit training that has not been run. What is proven is that the path exists end to end and the envelope is mapped.

Source: on-rig fine-tuning project, phases 0–4, one Arc Pro B70 on Windows with PyTorch XPU, 22 June 2026.

The serving substrate underneath

Worth a line because it is the connective tissue: partway through, Ollama came off that box in favour of something leaner — its memory overhead was the motivation. A Windows-native Vulkan dual-card substrate that owns config, the exact launch recipe, process lifecycle and structured status, behind a minimal OpenAI-compatible surface. It ran a 30B mixture-of-experts dual-split at 128k context alongside a 14B critic, from June 2026, and it's the direct ancestor of the Linux serving work in section 3.

Its most-earned design decision is one line: readiness means "can serve", not "process is up." Ignoring it produced a production incident on the Linux side five weeks later, when health checks that only probed the socket cheerfully reported success while a model was still loading — or already dying.

Source: dual-B70 Windows Vulkan serving substrate, June 2026. A dozen dated run directories with per-run manifests and telemetry, largely unmined.

5 · Does the output hold up?

Throughput is the easy half. These labs asked whether local models produce good enough output — and ran into a harder problem, which is that when a language model grades the work, you may be measuring the ruler.

The matrix wind tunnel — does self-refinement help?

Six rounds of overnight experiments on idle hardware, planner and critic deliberately running on different physical boxes: the 30B MoE on the dual-B70 machine, a 30B coder model on the RTX 5070. Each cell was a combination of planner, critic, prompt archetype, refinement laps and ordering, scored 0–100 by a held-out judge panel. 192 cells in the largest round.

Mean planning score by refinement laps. Round 4 used the original judge; round 6 re-scored with a neutral one. July 2026.
Refinement lapsRound 4 (original judge)Round 6 (neutral judge)
1 lap81.287.5
2 laps86.285.6
3 laps82.684.5
4 laps75.982.0

Read those two columns side by side. Round 4 tells a dramatic story — two laps is the sweet spot, four laps collapses. Round 6 says lap count barely matters, and the collapse was largely an artifact of the first judge's bias toward brevity. The same judge inflated the one real effect in the data — a concise author prompt, "shortest complete answer, lead with the decision" — from +2.8 points to +8.0.

The follow-on work quantified it: judges are near-deterministic on repeat (0.40 point sampling deviation) and wildly variable across rubrics (6.5 points average disagreement, up to 47). So resolving a genuine ~3-point effect takes roughly 19 lens-diverse votes but only about 1 repeat vote. Spend the evaluation budget on different rubrics, not on asking the same judge twice.

The value here wasn't the answer about laps — that's genuinely "meh". It was that the instrument flagged an effect, corrected it, explained it, and then caught its own measurement bias. Entirely on idle local hardware, overnight, at no marginal cost.

Source: github.com/djcdevelopment/windtunnel — dual Arc Pro B70 plus RTX 5070, 5–10 July 2026.

6 · Local vs cloud — quality, latency, money

The head-to-head (21 July 2026)

A scored documentation and decision-record task, run identically across the local model and two frontier cloud models. Fifteen cells, all successful.

Documentation and decision-record authoring task. Measured 21 July 2026.
Where it ranModelMean qualityMean latencyMarginal cost
Local, dual B70gpt-oss-120b93.8105.2 s$0.00
CloudGemini 3.1 Pro (preview)90.628.1 smetered
CloudGemini 3.5 Flash89.219.8 smetered

The local model won on quality, on two consumer GPUs, at zero marginal cost. The cloud won on latency by 4–5×, and that was the whole of its advantage on this task.

What cloud actually costs (23 July 2026)

A billing audit after standing up a cloud agent that reaches back into the local GPUs across an audited network boundary. The finding was not about tokens. Idle standing infrastructure produced an unexpected $36–38 bill — two managed agent runtimes at roughly $3.50/day each plus a small VM — while actual inference spend was trivial. If you are comparing local against cloud, compare the standing cost, not the per-token rate.

The ledger

Not a lab — the production record. Every model call routed through the local gateway is logged with backend, model, token counts and outcome, so the economics are measured rather than argued.

Offload ledger, watermark 5 August 2026. Totals across all backends: 1,199 calls, 2.80 M tokens in, 363 k tokens out.
WhereModelCost classCallsTokens inTokens outReal spend
Local, dual B70gpt-oss-120bsunk237326,012140,228$0.00
Local, dual B70Qwen3-30B-A3B Q4sunk33236,97015,431$0.00
CloudGemini 3.5 Flashtrial credit237411,17956,033$0.91
CloudGemini 3.1 Protrial credit1852,022,132150,362$5.35

618 of those calls landed on already-owned hardware. Every backend listed ran at a 100% success rate.

7 · What is not measured

Stated plainly so nobody cites this for something it doesn't cover.

If you're deciding whether to try this

The honest summary is that a 30B-class mixture-of-experts model runs comfortably fast on a single consumer card — 80 to 87 tokens a second — and that a 120B model is genuinely serviceable on two of them, at 26 to 29. A 70B works too, once you find the flag. The output quality is competitive with frontier cloud on real work, and you can fine-tune on the same hardware you serve from. What will actually stop you is none of those things: it's system RAM, context depth, and the fact that a local inference server will silently truncate your prompt and tell you everything went fine.

Buy the RAM. Cache your prefixes. Check your own payload sizes. And build the observation tool before you trust the dashboard — because on at least one of these platforms, the dashboard was reporting 5.117 volts and 8.55 gigahertz at idle, and cheerfully meant it.

Derek Ciula · Steppe Integrations · August 2026 · more writing →