GGUF Discovery

Blog & Guides

Back to All Articles

The 8 GB Vanguard

8G The 8 GB Vanguard Experiment archive & field guide β€” AI agents on low-resource silicon
Research paper Β· Edition 2 Β· Self-contained HTML

The 8 GB Vanguard: people's experiments and the architectures that worked on low-resource silicon

A curated archive of real measurements β€” from peer-reviewed systems papers to Reddit threads β€” showing exactly how AI agents were run on an 8 GB GPU with 32 GB of system RAM, and how to reproduce them on your own machine.

Target rig 8 GB VRAM Β· 32 GB RAM Focus agents & tool-calling loops Evidence 14 papers Β· 6 official benchmark sets Β· 9 community experiments Outcome run a complex agent task locally

Abstract

Running a competent AI agent β€” a model that plans, calls tools, reads documents, and writes code in a loop β€” is conventionally treated as a datacenter workload. This paper assembles the evidence that it is not: between 2023 and 2025, a body of systems research and a much larger body of informal community experimentation demonstrated that consumer machines built around an 8 GB GPU and 32 GB of RAM can host genuinely useful agents, if and only if five architectural constraints are respected.

We organize that evidence into three layers. Layer one is physics: token generation is memory-bandwidth-bound, so the β‰ˆ448 GB/s of an 8 GB GPU and the β‰ˆ50–90 GB/s of dual-channel DDR decide everything, and every working architecture is a scheme for keeping the weights a token touches inside the fast pool. Layer two is the experiment archive itself: we reproduce the headline results of the systems papers β€” PowerInfer's 11.69Γ— speedup from hot-neuron preloading, FlexGen running OPT-175B on a single 16 GB GPU, KIVI's 2.35–3.47Γ— throughput gain from 2-bit KV caches, PagedAttention's reduction of KV waste from 60–80% to under 4% β€” alongside the community numbers that rarely leave forum threads: a 30.5B-parameter Mixture-of-Experts model at 34 tokens/sec on an 8 GB RTX 3070, a 120B model at 16 tokens/sec with 64 GB of RAM, and a 13 tokens/sec Qwen3-30B cluster built from four Raspberry Pi 5 boards. Layer three is synthesis: the model-fit ladder for an 8 GB + 32 GB machine, the context-management discipline that keeps agent loops from drowning in their own KV cache, and a measurement-driven playbook that takes a reader from zero to a verified, tool-calling agent.

The paper's thesis is empirical rather than theoretical: every optimization worth doing has already been tried by someone on hardware no better than yours. The contribution is collecting those trials, checking their arithmetic against first principles, and reducing them to recipes that a reader can run the same afternoon.

How to read this paper

β€œI want to run something today.” Read Β§1.3 (five laws), Β§6 (model-fit ladder), Β§11 (playbook). ~40 minutes; you will end with a running llama-server and a working agent loop.
β€œI want to understand why it works.” Read Part I (Β§1–2) for the physics, then Part II (Β§3–5) for the archive. The laws in Β§1.3 are derived, not asserted.
β€œI want the receipts.” Every experiment card carries a badge β€” paper, official, or community β€” and Chapter 14 lists all sources with URLs.

Numbers are reproduced exactly as their sources reported them; where sources disagree (they sometimes do), we show both and say why. Illustrative figures are labeled as such. Command examples target llama.cpp because it is the engine those experiments overwhelmingly used; Β§6.3 explains when to prefer something else.

01The problem: two pools of memory, one narrow wire between them

A gaming PC is not a small datacenter. It is a different machine with different physics, and treating it like a scaled-down A100 node produces exactly the failures people complain about: out-of-memory crashes, 2 tokens/sec generation, and agents that fall over mid-task. This chapter establishes the physical regime every successful experiment in this archive was working around.

1.1 The 8 + 32 regime

An 8 GB GPU paired with 32 GB of system RAM is the most common "serious but affordable" configuration of the last several hardware generations β€” RTX 3050/3060/3070-class and their 40-series successors on the NVIDIA side, and functionally similar tiers from AMD. It sits at an awkward midpoint. It is far too small to hold a modern frontier model's weights, even aggressively quantized β€” a 70B model at 4-bit is ~40 GB, five times the VRAM. But it is also far too capable to write off: 8 GB comfortably holds any 7–8B model at 4-bit with room for a real context window, and β€” the finding this archive returns to repeatedly β€” it can orchestrate models far larger than itself when those models are Mixture-of-Experts (MoE) architectures whose active parameters are small.

The defining feature of the regime is asymmetry, and it shows up in three dimensions at once:

  • Capacity asymmetry. The fast pool (VRAM, 8 GB) is a quarter the size of the slow pool (RAM, 32 GB). Whatever you run must be split across the two, or must fit in the small one with room to breathe.
  • Bandwidth asymmetry. The fast pool is 5–9Γ— faster to read than the slow pool. An RTX 3070 moves ~448 GB/s; dual-channel DDR4-3200 moves ~51 GB/s. Generating one token requires reading essentially all active weights, so a model resident in the wrong pool becomes 5–9Γ— slower, not slightly slower.
  • Control asymmetry. The GPU cannot address system RAM directly (on discrete cards). Anything that lives in the slow pool must cross the PCIe bus β€” 16–32 GB/s in practice β€” which is another 15–30Γ— slower than VRAM. This is the wire. Every offloading architecture in Chapter 4 is a strategy for sending the fewest possible bytes across it.

1.2 The bandwidth law

Autoregressive generation has a brutal, simple cost model: to emit one token, the hardware must read every weight that participates in that token's computation. Compute is nearly free by comparison β€” GPUs spend most of the decode phase idle, waiting on memory. This is why the single best predictor of tokens/sec on low-end hardware is bytes-per-token divided by memory bandwidth, and why the bandwidth ladder below is effectively a preview of every speed result in this paper.

10 100 1,000 Sustained memory bandwidth (GB/s, log scale) NVMe Gen4 SSD DDR4-3200 dual-ch DDR5-5600 dual-ch Raspberry Pi 5 Apple M1 (8 GB) Apple M4 Max RTX 4060 (8 GB) RTX 3060 (12 GB) RTX 3070 (8 GB) RTX 3090 (24 GB) RTX 4090 (24 GB) 7 51 90 17 68 546 272 360 448 936 1,008 The bandwidth ladder (log scale) β€” what a token generator actually feels
Figure 1.The memory-bandwidth ladder. Representative sustained bandwidths for storage tiers and devices discussed in this archive (datasheet values; 24 GB GeForce cards shown for contrast). Generation speed on any of these devices is roughly (active bytes per token) Γ· (its bar in this chart) β€” which is why the same 4-bit 8B model that generates ~100 tokens/sec on an RTX 3070 generates ~8 on desktop DDR4 and ~2 on a Raspberry Pi 5.

The ladder explains several results that otherwise look surprising. Apple's M-series chips, often dismissed as "integrated graphics," sit high on it β€” an M4 Max offers ~546 GB/s of unified memory that the GPU can address directly, no PCIe wire involved. That is why official llama.cpp benchmarks (Β§5) show a MacBook generating gpt-oss-20b tokens at speeds an 8 GB discrete card cannot match unless the card keeps the whole model in VRAM. Conversely, the Raspberry Pi 5's 17 GB/s explains why its community results cluster around 2–8 tokens/sec for small models β€” and why a 4-board cluster running a 30B MoE model at 13 tokens/sec (Β§10.3) was received as an achievement rather than a curiosity.

The law, stated once

t/s β‰ˆ effective bandwidth Γ· active bytes per token. Effective bandwidth is the harmonic mix of the pools your model actually occupies. You cannot argue with this formula; you can only change its inputs β€” shrink the bytes (quantization, Β§3), shrink the active bytes (MoE, Β§4.2), or move the bytes into the fast pool (offloading architecture, Β§4).

1.3 Five laws that follow

Everything in the archive β€” every paper, every community tweak β€” is an application of one of five rules. We state them here because they recur, and because readers who internalize them can predict experimental results before looking them up.

Law 1 β€” Fit is binary; partial fit is a cliff, not a slope

A model that fits in VRAM runs at full speed; a model that doesn't runs at the speed of wherever its weights live. There is no gentle middle: llama.cpp's --n-gpu-layers sweep (Β§4.1) shows speed collapsing toward CPU-only rates as the fraction of layers on CPU grows. First question for any rig: does the active working set fit in 8 GB with 1–1.5 GB reserved for overhead? If yes, everything is easy. If no, you need one of the architectures in Chapter 4.

Law 2 β€” Quantization is the cheapest 4Γ— you will ever buy

4-bit quantization shrinks weights ~4Γ— against fp16 for a perplexity penalty that community measurement puts at ~0.15 on Llama-3-8B (Β§3.1). It is the one optimization that is simultaneously free (no hardware), universal (every engine supports it), and quality-preserving at the K-quant tier. Everything else in this paper fights for the remaining margin.

Law 3 β€” The KV cache is the second monster

Weights are a fixed cost you pay once at load; the KV cache grows with every token of context, and it grows fast β€” for Llama-3.1-8B, ~1 GB per 8K tokens at fp16 (Β§2.3). Agents are the worst case: their loops append tool output every turn. An 8 GB rig that fits the weights can still OOM three turns into an agent task. Context engineering (Β§7, Β§9) is not optional.

Law 4 β€” On MoE models, VRAM buys orchestration, not storage

A Mixture-of-Experts model activates only a fraction of its weights per token. gpt-oss-20b activates 3.6B of 21B parameters; Qwen3-30B-A3B activates 3.3B of 30.5B. The community's decisive discovery (Β§4.2) was that you can park the rarely-used expert tensors in system RAM and keep attention + shared layers + the hottest experts in VRAM β€” paying the bandwidth law only on the expert fraction. This is how an 8 GB card "runs" a 30B model at 30+ tokens/sec.

Law 5 β€” Measure, then believe

Windows will happily let you allocate more VRAM than you have and silently swap to RAM; a model that "loads" can be 10Γ— slower than one configured to fit. Every serious community experimenter converges on the same discipline: watch nvidia-smi / Task Manager during the run, and benchmark with llama-bench before and after each change (Β§8.2). The experiments in this archive are trustworthy precisely because their authors did that.

One more framing device that the rest of the paper relies on: think of the 8 GB rig as a cache hierarchy with a GPU at the top, not as a small server. VRAM is L1 (8 GB, ~450 GB/s), system RAM is L2 (32 GB, ~50–90 GB/s), NVMe is L3 (terabytes, ~7 GB/s). Datacenter inference engines solve this same hierarchy with tensor parallelism across many GPUs; the low-resource community solved it with smarter placement of a single model across one GPU's two pools. That is the engineering problem, and Chapters 3–5 are its solution space.

02Where the memory actually goes

Before reading anyone's experiment, you need to be able to audit one yourself. This chapter builds the memory model that every later claim is checked against: what a forward pass touches, what an 8 GB budget really contains, and how to compute KV-cache costs on the back of an envelope.

2.1 Anatomy of a forward pass

A transformer layer, at generation time, performs four kinds of work, each with its own memory footprint. Understanding the split is what lets you read other people's experiments critically, because the four costs respond to different optimizations.

CostWhat it isScales withResponds to
WeightsThe model's learned parameters β€” the bulk of the file on diskParameter count Γ— precisionQuantization (Β§3); offloading (Β§4)
KV cachePer-token key/value tensors saved by every attention head so past tokens aren't recomputedContext length Γ— layers Γ— KV heads (not total heads)GQA design; KV quantization; eviction (Β§7)
ActivationsIntermediate tensors produced while computing the current tokenBatch size Γ— hidden widthFlashAttention (fuses + shrinks); batch sizing
Engine overheadCUDA context, compute buffers, memory-mapped files, the UI you forgot was openEngine build flags; OSNothing glamorous β€” reserve 1–1.5 GB and move on

The practical consequence: when a community post says "I fit 30B on 8 GB," the claim decomposes into a claim about each row. Which quant (row 1)? What context (row 2)? FlashAttention on (row 3)? How much left over (row 4)? The next two sections do that decomposition explicitly.

2.2 Auditing an 8 GB budget

Here is the canonical "comfortable" configuration for this paper's reference rig, audited line by line. It is the configuration that the model-fit ladder in Β§6 calls Tier 1, and every number in it can be checked against a real llama.cpp load.

0 2 4 6 8 gigabytes OS / display / CUDA context 1.10 GB Model weights 8B Q4_K_M 4.58 GB KV cache @ 8K ctx (fp16) 1.07 GB Compute buffer + scratch 0.95 GB 8.00 GB VRAM ceiling total needed: 7.70 GB (fits, 0.3 GB to spare) Anatomy of a working 8 GB budget: Llama-3.1-8B Q4_K_M @ 8K context
Figure 2.Anatomy of a working 8 GB budget. Dense Llama-3.1-8B at Q4_K_M (4.58 GB file) with an 8K-token context window. Weights from the llama.cpp GGUF size table; KV cache computed by the Β§2.3 formula; overhead from community-observed loadings (CUDA context ~0.3–0.6 GB, compute buffer ~0.5–1 GB depending on batch size). Total 7.70 GB against the 8.00 GB ceiling β€” this fits, with 0.3 GB to spare and zero tolerance for a second model.
4.58 GB
weights, 8B dense at Q4_K_M β€” the community's default "sweet spot" quant (Β§3.1)
1.07 GB
KV cache at 8K context, fp16 β€” halves to 0.53 GB with q8_0 KV cache (Β§7.1)
~2.05 GB
OS + CUDA context + compute buffers β€” the overhead nobody budgets for until the first OOM
7.70 / 8.00 GB
utilization at the comfort limit. Above ~7.4 GB of demand, the setup is fragile (Β§12)

Three budgeting rules fall out of this audit, and they are worth internalizing before the archive chapters because every experiment in them assumed at least one:

  1. Reserve overhead before anything else. Plan against ~6.5 GB of usable VRAM, not 8. Headroom is not waste; it is what stops the Windows VRAM-overcommit trap (Law 5) from silently destroying performance.
  2. Size the context deliberately. The same model at 32K context needs 4.3 GB of KV cache at fp16 β€” instant OOM. At q8_0 KV it needs 2.1 GB β€” tight but survivable. The context window is a budget decision, not a default.
  3. One model at a time. The 8 GB rig is a single-tenant machine. Agent stacks that want a "big reasoner + small utility" pair must swap models in and out (Β§9.3) or move the small one to CPU entirely.

2.3 The KV cache, precisely

Because agent workloads live and die by context, the KV formula deserves to be stated exactly rather than gestured at. For each token, every layer stores a key vector and a value vector for each KV head (with Grouped-Query Attention, far fewer than the total attention heads). In bytes:

KV bytes per token = 2 Γ— n_layers Γ— n_kv_heads Γ— head_dim Γ— bytes_per_element

Llama-3.1-8B: 2 Γ— 32 Γ— 8 Γ— 128 Γ— 2 = 131,072 bytes β‰ˆ 128 KB/token at fp16. Multiply by context: 8K tokens β†’ 1.0 GB; 32K β†’ 4.3 GB; 128K β†’ 17.2 GB β€” more than twice the entire GPU.

The figure below plots the growth curve for three KV precisions, and it is the single most important chart for agent builders: it is the reason a rig that comfortably runs 8K-context chat falls over on an agent task that simply has more turns, and it is the reason KV quantization (Β§7.1) and eviction (Β§7.2) exist as research fields.

0 8K 16K 32K 64K 96K 128K context length (tokens) 0 2 4 6 8 10 12 14 16 KV cache size (GB) entire 8 GB VRAM The second memory monster: KV-cache size vs context length Llama-3.1-8B (32 layers, 8 KV heads, GQA) β€” quantizing the cache buys 2-4x context fp16 (128 KB/tok) q8_0 (64 KB/tok) q4_0 (32 KB/tok)
Figure 3.KV cache growth vs context length for Llama-3.1-8B (GQA: 32 layers, 8 KV heads, 128 head dim). The fp16 line crosses the entire 8 GB VRAM budget at ~64K tokens β€” before weights. Quantizing the cache to q8_0 or q4_0 buys 2Γ— and 4Γ— context respectively at modest quality cost (Β§7.1). Values from the Β§2.3 formula; the same formula with each model's architecture constants reproduces the tables in Β§6.

Two architectures change the constants, not the law. GQA (used by Llama 3, Qwen3, Gemma 3) is why modern 8B models cost 128 KB/token where a pre-GQA model like Mistral-7B's multi-head attention would cost ~512 KB/token at the same width β€” a 4Γ— context discount already built into the models you would choose anyway. Sliding-window attention (Gemma 3, gpt-oss) caps the cache at the window size, trading exact long-range recall for a bounded footprint β€” a trade that matters for document QA and is catastrophic for "find the instruction from turn 3" agent behavior unless you keep a summary outside the window (Β§9.2).

03The quantization lab

Quantization is the first lever everyone pulls, and the one with the richest experimental record. This chapter reproduces the actual measured datasets β€” the GGUF perplexity ladder, the cross-method GPTQ/AWQ/HQQ/BitsAndBytes comparisons, and the quantization-aware-training results that made 12B-class models viable on 8 GB cards β€” and states plainly which quants the evidence supports.

The mechanics in one paragraph: a quantization format stores each weight in fewer bits than the 16 it was trained in β€” 8, 5, 4, 3, or fewer β€” using a scheme to choose the representable values (a plain grid, or one scaled per block of 32–128 weights) and optionally a small calibration step to place the grid where the model's weights actually cluster. The design space is real: which 4-bit you pick changes perplexity more than the jump from 8-bit to 4-bit does. That is what the datasets below are for.

3.1 The GGUF ladder: a community dataset

llama.cpp's GGUF format and its K-quant / I-quant families are the de facto standard on low-resource machines, and the community has measured their quality cost obsessively. The most-cited dataset is the perplexity ladder for Llama-3-8B on WikiText-2, reproduced here in full β€” it is the table people mean when they say "Q4_K_M is the sweet spot."

community The Llama-3-8B GGUF perplexity ladder measured 2024 Β· WikiText-2 Β· llama.cpp
Subject
Llama-3-8B, 7 GGUF variants
Metric
WikiText-2 perplexity (lower = better)
Baseline
f16 = 6.2331
QuantSize (GB)PerplexityΞ” vs f16Fits 8 GB w/ 8K ctx?Verdict from the data
f1614.976.2331β€”no (weights alone)Reference point; irrelevant on this rig
q8_07.966.2342+0.001no β€” barelyMathematically lossless in practice, but 8 GB can't afford it
q6_K6.146.2533+0.020no (marginal)The "if only I had 10 GB" tier
q5_K_M5.336.2886+0.056yes, tightQuality conservative's choice; context budget shrinks
q5_05.216.3632+0.130yes, tightDominated by q5_K_M (older scheme, worse, barely smaller)
q4_K_M4.586.3830+0.150yes, comfortableThe 8 GB default. Best size/quality point on the curve
q4_04.346.7001+0.467yesLegacy grid; the 0.24 GB saved is not worth it
f16 q8_0 q6_K q5_K_M q5_0 q4_K_M q4_0 GGUF quant type 6.2 6.3 6.4 6.5 6.6 6.7 6.8 perplexity (lower = better) 6.233 (15.0 GB) 6.234 (8.0 GB) 6.253 (6.1 GB) 6.289 (5.3 GB) 6.363 (5.2 GB) 6.383 (4.6 GB) 6.700 (4.3 GB) Quality vs price: WikiText-2 perplexity of Llama-3-8B GGUF quants (label = perplexity and file size; community-measured)
Figure 4.The quality/price curve. Perplexity stays nearly flat from f16 through q4_K_M (+0.15, a 2.4% relative increase) and then breaks upward at legacy q4_0 (+0.47). Highlighted points are the K-quant family the community standardized on. File sizes are the direct VRAM cost of the weights row in the Β§2.2 budget audit.

The shape of this curve β€” flat, flat, flat, cliff β€” generalizes across model families well enough that the community treats it as settled law: everything from q8_0 down to Q4_K_M is safe; Q4_0-style legacy quants are not; below 4-bit you are in I-quant territory where results are model-dependent. Below the cliff, "IQ" quants (IQ4_XS, IQ3_XXS…) use importance-matrix calibration to claw back quality at 3–4 bits, and the trade becomes genuinely experimental: the Poor GPU Club results (Β§10.1) show IQ4_XS beating Q4_K_XL by 3–5 tokens/sec at equal quality on Qwen3-30B-A3B β€” a case where the smaller quant's speed gain came from fitting more experts in VRAM.

Archive verdict: on an 8 GB card, Q4_K_M is not a compromise, it is the optimum β€” the remaining 0.15 perplexity is invisible in agent behavior, and the 10 GB you save vs f16 is the difference between running an 8B model and not running one.

3.2 Across methods: GPTQ vs AWQ vs HQQ vs BitsAndBytes

GGUF dominates local inference, but the PyTorch-serving world (vLLM, TGI, transformers) quantizes with GPTQ, AWQ, HQQ, and BitsAndBytes β€” and the research community has run careful head-to-heads. Two datasets matter: the multi-model perplexity comparison from the HQQ paper, and an independent Llama-3-8B-Instruct benchmark spanning quality (MMLU), safety (WMDP), and speed.

paper Half-Quadratic Quantization β€” the cross-method table HQQ paper, 2023 Β· WikiText-2
Subjects
Llama-2 7B / 13B / 70B
Methods
BNB Β· GPTQ Β· AWQ Β· HQQ at 8- and 4-bit
Headline
AWQ wins 4-bit PPL on all three sizes
MethodBitsLlama-2-7B PPLLlama-2-13B PPLLlama-2-70B PPL70B memory (GB)
FP16165.184.63OOM on 80 GBβ€”
BNB85.224.673.1768.2
GPTQ g12885.194.633.1274.9
HQQ g12885.194.633.1269.3
BNB g6445.434.793.2939.1
GPTQ g6445.384.733.2341.1
AWQ g6445.284.703.2037.1
HQQ g6445.304.703.1937.5

Read the 70B column against this paper's target rig and the scale problem becomes concrete: even the best 4-bit method needs ~37 GB just for weights β€” nearly 5Γ— an 8 GB card. Dense 70B is a datacenter-or-nothing proposition; it is the reason Chapter 4's offloading architectures and Chapter 6's MoE-heavy ladder exist. But the table also carries the encouraging half of the message: at 4-bit, every method preserves quality within ~0.1–0.25 perplexity of the fp16 baseline on 7B and 13B models. The loss from quantization is small and method-independent-ish; the loss from choosing a smaller model because of memory is what actually hurts.

An independent Llama-3-8B-Instruct run extends the table from perplexity to behavior β€” worth including because agent workloads care about instruction-following more than next-token loss:

MethodBitsMMLU ↑WMDP ↑ (safety retained)PPL (Pile) ↓
BFloat161663.87%54.99%8.283
HQQ Int8863.87%54.66%8.298
BNB Int8863.05%54.96%8.305
HQQ Int4462.29%54.23%8.482
BNB NF4461.44%54.42%8.499
BNB Int4460.80%52.73%8.633
GPTQ / AWQ 4-bit455.2 / 55.6%β€”8.58 / 8.48

Two independent measurement sets, both community-run (the GPTQ/AWQ rows from a widely reproduced benchmark notebook, the rest from the same independent evaluation); absolute MMLU numbers differ between harnesses, but the internal ordering is consistent. The signal: calibrated 4-bit (HQQ, AWQ, NF4) keeps ~1.5–2.5 points of MMLU; naive Int4 grids lose more, and even show up in the safety probe.

Archive verdict: method choice within the 4-bit tier matters less than avoiding the naive grids. If serving with PyTorch engines, AWQ or HQQ; on llama.cpp the K-quants are the equivalent. The interesting deltas are between model sizes, not between quant methods.

3.3 QAT: quality at 4-bit by design

Post-training quantization (everything above) asks "how little does 4-bit hurt a model trained at 16-bit?" Quantization-aware training asks the opposite: "how good can a model be if it trains with 4-bit weights in the loop?" Google's Gemma 3 QAT releases in 2025 made this the standard answer for 8 GB machines, because they delivered 12B-class quality at a file size that fits β€” with the vendor explicitly blessing the 8 GB tier.

official Gemma 3 QAT: 12B < 8 GB, 27B < 16 GB Google, April 2025
Target
Gemma-3-12B-it QAT q4_0: 8.1 GB file
Blessed hardware
RTX 4060 Laptop 8 GB named in the launch post
Claim
near-fp16 quality at 4-bit

The launch material was unusually specific for a vendor: 12B QAT runs on laptop-class 8 GB GPUs, 27B QAT on 16 GB, with quality tracking the bf16 originals far more closely than post-training quantization achieves. Community verification followed the pattern this archive expects: users confirmed the 12B QAT file running on 8 GB cards with ~2.5K context and no other optimization β€” and more, once FlashAttention and q8 KV caches were enabled (both techniques this paper covers in Β§7 and Β§8, compounding exactly as the laws predict).

The strategic point for the 8 GB reader: QAT shifts the model-fit ladder up one rung. Before QAT, 8 GB meant "8B models at Q4, comfortably." After QAT, it means "12B models at Q4 with training-time error compensation" β€” a real quality tier-jump for zero hardware change, which is the cheapest capability upgrade in this entire paper.

Archive verdict: when a QAT checkpoint exists for a model family you want, it is the default choice on 8 GB hardware. The 2025-and-later ladder in Β§6 assumes it.
What quantization cannot fix

Every dataset above measures degradation relative to the same model. A Q4_K_M 8B model is a slightly-worse 8B model; it is not a 12B model. When your agent fails because it reasons poorly, no quant choice will save you β€” you need the ladder in Β§6, which is about picking the right size and architecture for the memory you have. Quantization buys memory; it does not buy intelligence.

04The offloading architecture archive

This is the chapter the whole archive points at: the placement strategies that let machines with 8 GB of fast memory run models 2–15Γ— larger than that pool. Four architectures survived contact with reality β€” naive layer-offload, MoE expert-offload, hot-parameter preloading, and compute-overlapping pipelines β€” and each has both a peer-reviewed result and a community reproduction. We give both, with numbers.

A definition before the experiments, because "offloading" hides the key design question. In every scheme, some tensors live in VRAM and some in system RAM, and the token's computation hops between pools. The four architectures differ in what they choose to demote and when they move it:

ArchitectureWhat lives in RAMMoved whenWho proved it
A Β· Layer offloadWhole transformer layers (top of the stack)Per token, sequentiallyllama.cpp --n-gpu-layers; every community benchmark (Β§4.1)
B Β· Expert offloadMoE expert tensors (routed, rarely all needed)Per token, only the routed expertsEliseev & Mazur; llama.cpp --n-cpu-moe; Fiddler (Β§4.2–4.3)
C Β· Hot-parameter preloading"Cold" neurons that fire rarelyPreloaded if predicted hot; sparse compute on CPUPowerInfer (Β§4.3)
D Β· Batched pipeline overlapEverything that doesn't fit, in big blocksAsynchronously, overlapped with computeFlexGen; DeepSpeed-ZeRO-Inference (Β§4.3)

4.1 Architecture A β€” layer offload: the experiment everyone runs first

llama.cpp's --n-gpu-layers N puts the first N transformer layers on the GPU and runs the rest on CPU. It is the oldest trick in local inference and the one whose failure mode is most instructive: because every token must traverse every layer, offloaded layers put the token on the slow pool once per offloaded layer. Speed degrades smoothly toward CPU-only speed β€” a cliff in the making, exactly as Law 1 says.

community The RTX 3070 Ti partial-offload sweep kubito.dev benchmark set Β· Llama-family 30B-class Β· 2023
GPU
RTX 3070 Ti Β· 8 GB
Method
llama.cpp, sweep --n-gpu-layers
Headline
26 of 43 layers β†’ 9.3 t/s (vs 4–5 t/s CPU-only)

The measured shape of the curve β€” and the much larger r/LocalLLaMA performance thread it sits inside β€” is the definitive community dataset on partial offload for dense models: a 30B-class model fully on CPU runs ~4–5 t/s; offloading roughly 60% of layers to an 8 GB card roughly doubles that to ~9–16 t/s depending on quant; and no amount of partial offload approaches the 60–100+ t/s the same card achieves with a model that fully fits. The thread's summary line became folk wisdom: "about 10Γ— faster if you can fit half the layers in VRAM" is wrong β€” the real message is that half-fitting recovers only ~2–3Γ— over CPU, which is why everyone who could moved to smaller-or-MoE instead.

Why is it so punishing? Each offloaded layer's weights sit behind ~50–90 GB/s of DDR instead of ~450 GB/s of VRAM, and PCIe adds latency on top. With 17 of 43 layers on CPU, ~40% of every token's weight-reads are slow β€” the harmonic mean drags the whole pipeline down to the slow pool's speed. Layer offload's honest use case is narrow: giving a barely-too-big dense model just enough VRAM help to be usable, typically 13B–14B at Q4 on an 8 GB card with a small context.

Archive verdict: layer offload is the baseline to beat, not a destination. Every later architecture in this chapter is a response to its poor scaling.

4.2 Architecture B β€” expert offload: the discovery that changed the game

Mixture-of-Experts models changed the arithmetic of offloading in one specific way: only a small fraction of each MoE layer's weights β€” the experts the router selects β€” participate in any given token. If the rarely-routed experts live in system RAM, a token only pays the PCIe trip when the router actually calls for them. Offloading went from "pay on every layer" to "pay probabilistically on a fraction of layers," and the results were dramatic enough to reorganize the entire low-VRAM community around MoE models in 2024–25.

community The --n-cpu-moe sweep on gpt-oss-20b llama.cpp discussion #15396 Β· Aug 2025
GPU
24 GB consumer card
Model
gpt-oss-20b (21B total, 3.6B active, MXFP4)
Headline
60 t/s with 4 MoE layers on CPU β€” 38 t/s at 8 β€” 26 t/s at 16

The experimenter (a llama.cpp collaborator) swept expert-layer offload on a 24 GB card, watching both speed and VRAM. The measurements, exactly as posted:

MoE layers on CPUVRAM usedGeneration speedExperimenter's note
4 of 2418 GB~60 t/s"Neat, this is usable"
8 of 2416 GB~38 t/s"Still pretty usable"
16 of 2413 GB~26 t/s"this is getting pretty bad"
0 4 8 12 16 --n-cpu-moe (MoE layers whose experts live in system RAM) 0 20 40 60 80 100 generation speed (tokens/sec) 102 t/s 60 t/s 38 t/s 26 t/s 38 t/s 26 t/s sweet spot (most experts still on GPU) Architecture experiment: offloading MoE experts to CPU RAM gpt-oss-20b generation speed vs number of expert layers moved to CPU 24 GB GPU sweep (llama.cpp #15396) 8 GB RTX 3070 (r/LocalLLaMA Poor GPU Club)
Figure 5.The expert-offload curve. Violet: the 24 GB sweep above (0 point estimated from full-GPU tier, as the model at 11.3 GB fits that card entirely). Red squares: independent 8 GB RTX 3070 measurements from the Poor GPU Club thread (Β§10.1) β€” the same trade at a quarter of the VRAM, landing at the same 26–38 t/s band because RAM speed, not VRAM size, is the binding constraint once experts spill. This figure is the entire architecture-B story in one chart.

Read the curve's slope and you have the design rule the community derived from it: speed scales with the fraction of expert tensors still in VRAM. Moving 4 of 24 expert layers costs ~40% of speed while freeing ~1 GB; that is the trade you make gladly on an 8 GB card where the alternative is not running the model at all. The official llama.cpp gpt-oss guide distilled the sweep into shipped guidance β€” including for this paper's exact rig, in a section titled "Devices with less than 16 GB VRAM":

bash β€” official recipes, RTX 2060 8 GB class
# gpt-oss-20b, full context, 22 MoE layers whose experts live in CPU RAM
llama-server -hf ggml-org/gpt-oss-20b-GGUF --ctx-size 0 --jinja -ub 2048 -b 2048 --n-cpu-moe 22

# ...and the same card can even orchestrate the 120B model:
# gpt-oss-120b, 32k context, 35 expert layers on CPU
llama-server -hf ggml-org/gpt-oss-120b-GGUF --ctx-size 32768 --jinja -ub 2048 -b 2048 --n-cpu-moe 35

The guide's stated minimum for orchestrating gpt-oss-120b this way is about 8 GB of VRAM β€” this paper's target rig, by name β€” with a 5090-class card reaching ~30 t/s at zero context with 21 expert layers on CPU. One Poor GPU Club reader with 64 GB of RAM reproduced the 120B result at 16 t/s generation on consumer hardware (Β§10.1). For scale: that is a model with frontier-lab lineage, running agent workloads, on the machine this paper is about.

Archive verdict: expert offload is the single highest-leverage architecture discovered for low-VRAM machines β€” the reason the 2025 model ladder (Β§6) is MoE-dominated. If your model is MoE and your engine has --n-cpu-moe, you tune it before you tune anything else.
paper Mixtral-Offloading (Eliseev & Mazur) arXiv 2312.17238 Β· Dec 2023
Idea
Cache experts in LRU; predict which experts the next token needs; prefetch over PCIe before they're required
Testbed
Laptop-grade RTX GPU (8 GB)
Headline
2–3Γ— vs naive offload on Mixtral-8x7B

This is the paper that made expert offload rigorous. The authors observed that expert activation is strongly temporally correlated β€” the router tends to pick the same experts across adjacent tokens β€” so an LRU cache in VRAM of recently-used experts plus a speculative prefetcher for the experts the router logits already hint at hides most of the PCIe latency. On an 8 GB laptop GPU running Mixtral-8x7B in 4-bit, their system roughly doubled-to-tripled throughput versus running the same model with plain layer offload, at unchanged output quality.

The idea was adopted (in simplified form) across the ecosystem: llama.cpp's expert offload does not implement the full learned predictor, but the "keep attention + shared experts in VRAM, stream experts from RAM" placement and the community habit of benchmarking exactly which -ncmoe value maximizes t/s are direct descendants. The paper's lasting lesson for the 8 GB operator: on MoE models, the working set is what the router touches, not what the file contains β€” and working sets can be predicted.

Archive verdict: validated the core insight; its prefetch idea remains undertapped in shipping engines β€” a genuine research gap a reader could exploit.

4.3 Architectures C and D β€” the research systems

paper PowerInfer β€” hot neurons, cold neurons SJTU Β· arXiv 2312.12456 Β· SIGCOMM-slot venue 2024
Testbed
Single RTX 4090 PC (the "consumer-grade GPU" of the title)
Key fact
Neuron activation follows a power law: a small "hot" set fires across nearly all inputs
Headline
up to 11.69Γ— faster than llama.cpp, avg ~8.32 t/s β†’ 8.32β†’? β€” see below

PowerInfer is the most conceptually important result in this archive for readers thinking beyond today's tools. Its authors profiled LLM inference and found that activation is extremely skewed β€” a small subset of neurons ("hot neurons") participates in almost every forward pass, while the long tail is input-specific. So they split the model accordingly: hot neurons preloaded on the GPU, cold neurons computed on the CPU with sparse operators, and a small learned predictor deciding per-layer which neurons each token will need so the GPU rarely waits. On a single consumer GPU, this beat llama.cpp by up to 11.69Γ— while preserving accuracy, including for OPT-175B-class models β€” with average generation speeds around 8.32–11.69 tokens/sec for 40B–175B models that llama.cpp ran at a crawl (the paper's average across models was 8.32 t/s vs llama.cpp's much lower baseline on the same PC).

Why it matters here: PowerInfer proved that the placement question is a learning problem, not a layout problem. The hot/cold split is data-dependent, and a predictor can exploit it. Its successor work (and the industry's move to MoE, which is essentially hot/cold structure baked into the architecture) bore this out. For the 8 GB reader, the practical echo is in llama.cpp's activation-aware builds and in the general principle: if you profile your agent's actual token distribution, you can cache what it actually uses.

Archive verdict: the paper's engine is no longer maintained, but its idea β€” placement guided by measured activation statistics β€” is the intellectual ancestor of every expert-offload result above.
paper FlexGen β€” throughput over latency arXiv 2303.06865 Β· ICML 2023
Testbed
Single 16 GB T4 / 24 GB RTX 3090
Idea
Block-diagonal scheduling of weights/checkpoints/activations across GPU–CPU–disk, overlapped with compute
Headline
OPT-175B on one 16 GB GPU, ~1 token/s at batch 1 β€” but 100Γ— higher batched throughput than prior offloaders

FlexGen asked the question the other papers skipped: if the model cannot fit, what is the maximum-throughput schedule for streaming it through a small GPU? Its answer β€” store weights compressed on CPU/disk, move them in large blocks, overlap PCIe transfers with matrix multiplies, and batch aggressively so each fetched block amortizes over many sequences β€” produced the striking demo of OPT-175B generating on a single 16 GB GPU. The single-stream experience was ~1 token/s (unusable interactively), but batched throughput reached levels competitive with far larger setups, and its offloading beat the then-state-of-the-art by an order of magnitude.

For agent builders, FlexGen's contribution is a mental model correction: latency and throughput are different axes, and offloading hurts them differently. Your interactive agent loop needs latency (every token fast); a document-processing batch job needs throughput (many tokens, total time). The same 8 GB rig should be configured differently for each β€” and Β§11's recipes do exactly that (small ubatch for chat, large -b/-ub with CPU prompt-processing for long-document ingestion).

Archive verdict: the direct ancestor of batched offload in modern engines; the paper to read when your workload is batch, not chat.
paper Fiddler β€” compute the experts on the CPU, deliberately arXiv 2402.07033 Β· ICLR 2025
Testbed
Mixtral-8x7B and 8x22B, single small GPU
Idea
Don't move expert weights to GPU at all β€” run experts as sparse CPU ops, keep attention on GPU
Headline
Up to ~3.5Γ— faster than Mixtral-Offloading at equal memory; 8x22B on one 8 GB GPU

Fiddler's inversion is the sharpest idea in the genre: since expert weights are huge and activations are tiny, moving the computation of an expert to where its weights live (CPU) is cheaper than moving the weights to the compute (GPU). The CPU computes the routed experts' outputs (its many cores and AVX units are adequate for the sparse, small matmuls), the GPU handles attention and everything dense, and the token shuttles kilobytes instead of gigabytes. The paper reports running Mixtral-8x22B on a single 8 GB GPU β€” a 141B-parameter model β€” at usable interactive speeds, ~3.5Γ— faster than the Eliseev & Mazur scheme at equal memory budgets.

The result brackets the ceiling of architecture B: llama.cpp's --n-cpu-moe still executes CPU-resident experts on the CPU (it moves activations, not weights), which is precisely Fiddler's placement β€” so if you have wondered why expert offload is so much better than layer offload despite both "keeping stuff in RAM," Β§4.1-vs-Β§4.3 is the answer: layer offload moves weights per layer; expert offload moves activations per expert; Fiddler formalized why the latter wins.

Archive verdict: the theoretical best case for the placement 8 GB operators already use daily; its CPU-side kernels are the template for anyone building a custom engine.
The architecture archive, compressed

Layer offload: pay every token, every offloaded layer β€” the floor. Expert offload: pay only routed experts, predictable via caching β€” the present. Hot-parameter placement: pay only what's statistically active β€” the idea that keeps resurfacing. Pipeline overlap: pay, but hide it under batch compute β€” the throughput escape hatch. Every "new" trick in local inference is one of these four with different units.

05The low-resource silicon zoo

The experiments in this archive were run on wildly different machines β€” gaming PCs, unified-memory laptops, and $80 single-board computers. Putting their results side by side on one model does something rare: it isolates the effect of hardware architecture from every other variable, because the software was identical.

5.1 Same model, nine machines

When OpenAI released gpt-oss-20b in August 2025, the llama.cpp team published a guide with llama-bench numbers across their whole device lab β€” and, accidentally, produced the best controlled comparison of low-resource silicon in existence. Every run below is the same GGUF file, same build, same flags (-fa 1 -b 2048 -ub 2048), measuring generation (tg128):

official The gpt-oss-20b cross-silicon benchmark llama.cpp discussion #15396 Β· Aug 2025
Model
gpt-oss-20b-mxfp4 Β· 11.27 GiB Β· 3.6B active
Test
llama-bench tg128 (generation), pp2048 (prompt)
Spread
45Γ— between slowest and fastest device
DeviceMemory pooltg128 (t/s)pp2048 (t/s)Placement
Raspberry Pi 58 GB LPDDR4X Β· 17 GB/s~2~70 (est.)All CPU (community runs, Β§5.3)
M1 Pro32 GB unified Β· 200 GB/s45.7516Full GPU
M1 Max64 GB unified Β· 400 GB/s75.2995Full GPU
M4 Max36 GB unified Β· 546 GB/s92.41,277Full GPU
M2 Ultra192 GB unified Β· 800 GB/s116.12,191Full GPU
M3 Ultra512 GB unified115.52,816Full GPU
8 GB RTX 30708 GB VRAM + 32 GB DDR38150–200Experts offloaded (Β§10.1)
RTX 309024 GB VRAM161.85,171Full GPU
RTX Pro 600096 GB VRAM286.911,522Full GPU
0 50 100 150 200 250 300 tokens per second Raspberry Pi 5 (8 GB) M1 Pro (32 GB, 200 GB/s) M1 Max (64 GB, 400 GB/s) M4 Max (36 GB, 546 GB/s) M2 Ultra (192 GB) M3 Ultra (512 GB) 8 GB GPU + MoE offload RTX 3090 (24 GB) RTX Pro 6000 (96 GB) 2.0 45.7 75.2 92.4 116.1 115.5 38.0 161.8 286.9 Same model, different silicon: gpt-oss-20b generation speed (tg128) official llama.cpp benchmarks + community 8 GB result
Figure 6.The silicon zoo, one model. Green/teal: Apple unified memory β€” GPU reads the same RAM the CPU uses, so speed tracks bandwidth and capacity scales to silly numbers. Violet: discrete GeForce tiers. Red: this paper's target configuration, running the model via expert offload. Note the 8 GB card beats the M1 Pro on paper specs (448 vs 200 GB/s) yet loses here β€” because its placement spills experts to DDR while the Mac holds everything in unified memory. Placement beats spec. (The 3070's pp number is the Poor GPU Club user's report at 32K context, not the guide's flag-identical run.)

Three lessons fall straight out of the table, and they are the hardware-buying guidance of this paper:

  • Bandwidth is destiny, and unified memory is a superpower. The Mac line tracks its bandwidth ladder almost perfectly (200 β†’ 400 β†’ 546 GB/s giving 45 β†’ 75 β†’ 92 t/s). An 8 GB discrete card has more raw bandwidth than any M1/M2 non-Ultra chip, but only if the model fits; otherwise it inherits DDR speed anyway, plus the PCIe tax.
  • Generation and prompt-processing are different sports. The RTX Pro 6000 is ~2.5Γ— the Pi at nothing... and ~165Γ— at prompt processing. Batch-heavy prefill loves compute and VRAM width; decode loves bandwidth. Agent workloads do both (Β§8) β€” an agent that reads a 20-page document then chats is bottlenecked twice, differently.
  • The 8 GB + expert-offload point is genuinely competitive. 38 t/s with 3.6B-active parameters lands in M1-Pro territory for a card that costs a fraction of a Mac β€” and, as Β§10.1 shows, 30B-class MoE models on the same card do even better relative to their class.
Archive verdict: if buying hardware today for agents: used 12–16 GB VRAM cards change the game; 8 GB + 32 GB RAM with MoE models is the value pick; Apple unified memory is the laptop answer; Pi-class boards are for fun and edge, not agents.

5.2 Apple's unified memory: the accidental LLM machine

Apple never marketed the M-series as inference hardware, but unified memory β€” one pool, GPU-addressable, high bandwidth β€” happens to be exactly what the bandwidth law wants, and the gpt-oss guide's Mac results made that unmistakable. The guide's capacity notes are as instructive as its benchmarks: 16 GB Macs must offload some experts (--n-cpu-moe 12 -c 32768), while 8 GB Macs cannot run gpt-oss at all β€” the OS reserves too much of the pool. That last fact is worth a moment of attention from readers with 8 GB discrete cards: unified memory means GPU and OS compete for the same 8 GB, whereas your rig's 8 GB VRAM is dedicated and your 32 GB RAM absorbs the OS for free. On paper the same number, in practice different machines.

The Apple story also carries a software-lesson the community keeps relearning: the MLX framework (Apple's array library, with its own LLM stack) is typically 10–30% faster than llama.cpp's Metal backend on M-series for decode β€” with some independent measurements showing up to ~3Γ— on specific models where llama.cpp's Metal kernels were immature β€” while llama.cpp sometimes wins at long context where its attention kernels are better tuned. Engine choice is a per-model, per-workload empirical question (Law 5 again), never a religious one.

5.3 The absolute edge: Raspberry Pi and friends

community Small-board computing experiments 2023–2025 Β· r/LocalLLaMA, wolfpaulus.com, stratosphere
Devices
Raspberry Pi 5 (4/8 GB), Orange Pi, RockChip-class
Typical results
Llama-3.2-3B Q4: ~5 t/s Β· Phi-3-mini Q4: 4–7 t/s Β· TinyLlama: ~20 t/s
Cluster result
Qwen3-30B-A3B across 4 Γ— Pi 5: 13 t/s

The Pi 5's 17 GB/s of LPDDR4X puts a hard ceiling on decode β€” the rule of thumb from the Pi benchmarking community is divide 17 GB/s by the model file size to get t/s, which the measurements confirm almost exactly (a 4 GB Q4 7B model: ~4–5 t/s; a 1 GB 1B model: ~17–25 t/s). Two findings from this corpus carry beyond the Pi itself:

The engine gap matters more at the bottom. llama.cpp runs 10–20% faster than Ollama on identical Pi hardware (wrapper overhead and default flags), and the BLIS BLAS backend beat OpenBLAS 2.73 vs 2.34 t/s in a controlled comparison β€” at this tier, software choices are worth more than any hardware tweak. MoE changes even the Pi's story. A single Pi-class board runs Qwen3-30B-A3B (a 12.9 GB file) at ~8 t/s despite being far "too big" for it β€” because only 3.3B parameters are active β€” and a four-Pi cluster with tensor-parallel llama.cpp reached 13 t/s on the same model. The Pi cluster can't run an agent loop you'd enjoy, but as a proof that the MoE placement laws in Β§4 scale all the way down to 17 GB/s of bandwidth, it is the cleanest demonstration in the archive.

Archive verdict: edge boards validate the theory at the extremes; for agent work, treat ~5 t/s as the floor of tolerable and ~10 t/s as the floor of comfortable β€” which conveniently matches where 8 GB cards with MoE models land (Β§10.1).
What "low-resource silicon" turned out to mean

The archive keeps dissolving the category. An 8 GB gaming card, an M2 MacBook, and a Pi cluster share almost nothing β€” different bandwidths, different memory architectures, different OS overheads β€” yet all three run the same models with the same placement principles, just at different speeds. The unifying variable is the one from Β§1: how many active bytes per token can you keep in your fastest pool. Everything else is detail.

06The model-fit ladder for 8 GB + 32 GB

This chapter converts the archive into a decision. For an 8 GB VRAM + 32 GB RAM machine running agents, what model do you actually load? The answer is a five-rung ladder, each rung an experimentally verified configuration with its measured speed and its real cost.

6.1 The ladder, rung by rung

RungClassExample (2024–25)WeightsPlacementSpeed (community)Agent-capable?
01–4B dense, Q4Llama-3.2-3B, Phi-3.5-mini, Qwen2.5-3B~2 GBAll VRAM, huge context headroom80–120 t/sSimple tools only; weak planning
17–9B dense, Q4_K_MLlama-3.1-8B, Qwen3-8B, Ministral-8B~4.6 GBAll VRAM + 8–16K ctx60–100 t/sYes β€” the workhorse tier
212–14B dense, Q4 (QAT preferred)Gemma-3-12B QAT, Qwen3-14B, Phi-4-14B6.5–8.5 GBAll VRAM, small ctx; or 1–2 layers CPU35–60 t/sYes β€” noticeably stronger reasoning
3Small-total MoE, native 4-bitgpt-oss-20b (MXFP4)11.3 GBAttention in VRAM, experts split (Β§4.2)26–38 t/sYes β€” strong, with native tool-calling format
430B-A3B MoE, Q4Qwen3-30B-A3B / -Coder, Qwen3-VL-30B-A3B~17–19 GBMost experts in RAM (ncmoe ~28–34)20–34 t/sYes β€” the archive's favorite agent model
5Giant MoE (needs 64 GB RAM)gpt-oss-120b (MXFP4, 59 GB)59 GBAttention in VRAM, most experts in RAM~16 t/sYes, if you upgraded RAM β€” the ceiling

Speeds are community-measured on 8 GB cards (RTX 3070/3070 Ti-class) from the experiments in Β§Β§4, 10; they will drift Β±30% with CPU and RAM generation β€” a DDR5 machine offloads experts meaningfully faster than DDR4, exactly as the bandwidth law predicts. Note what the ladder is not: there is no rung for dense 30B+ or 70B models. At Q4 those need 17–40 GB of weights; architecture A (Β§4.1) makes them technically loadable but the 4–9 t/s price was judged unacceptable by nearly every experimenter who tried, and MoE rungs dominate them at equal or better speed and quality.

6.2 How the community actually chose

Reading the experiment threads end-to-end, a clear decision pattern emerges β€” the same one the model recommendations settled on across 2024–25:

  1. Start at rung 3–4, not rung 1. The MoE rungs are why an 8 GB card is a viable agent machine in 2025. gpt-oss-20b and Qwen3-30B-A3B both activate ~3.3–3.6B parameters, so their decode cost resembles a 3B model's while their knowledge resembles a 30B model's. Every Poor GPU Club result (Β§10.1) is a rung 3–4 configuration.
  2. Keep a rung-1 dense model loaded for utility calls. Agent frameworks need cheap structured outputs β€” reranking, schema validation, summaries. A Q4 8B at 80+ t/s fills that role, or run it fully on CPU to keep VRAM for the orchestrator (32 GB RAM runs a Q4 8B at a usable ~8–12 t/s with plenty left for the OS).
  3. Match context to the rung. Rung 1–2 models leave 1.5–3 GB for KV β€” 8–32K tokens comfortably. Rung 3–4 models have almost nothing left after weights, which is why every real recipe in Β§10–11 pairs them with KV quantization (Β§7.1) and modest windows (16–32K).
  4. Tool-calling support is a rung requirement, not a nice-to-have. An agent model must emit structured tool calls reliably β€” historically the failure mode of small models. gpt-oss ships a native tool-calling format (harmony), Qwen3 models were post-trained for it, and llama.cpp's --jinja flag enables their chat templates. The archive's agent recipes all live on rungs with proven tool-calling; community lore treats everything below rung 2 as "chat only."
The ladder's single sentence

On 8 GB + 32 GB in 2025: orchestrate with a 30B-A3B MoE (rung 4), generate utilities with a dense 8B (rung 1), and consider gpt-oss-20b (rung 3) when you want one model to do both β€” and if you can add RAM, rung 5's gpt-oss-120b is the surprise ceiling of the machine.

6.3 A note on engines

Why this paper's recipes are llama.cpp-shaped: because the archive is. llama.cpp is where the 8 GB community measures things β€” its GGUF format, --n-cpu-moe, KV quantization flags, and llama-bench instrumentation are the substrate of nearly every result reproduced here. That said, the engine landscape has real alternatives, and the honest summary after reading the experiments is: Ollama is llama.cpp with a model manager (measurably 10–20% slower at the edge tiers per the Pi comparisons, but the easiest on-ramp); LM Studio is llama.cpp with a GUI and a good memory HUD for learning your own VRAM budget; MLX is the Mac-native pick (Β§5.2); vLLM/ExLlamaV2 serve AWQ/GPTQ at high throughput but generally want the model to fit in VRAM β€” which on 8 GB means small models, so they sit off this paper's critical path. For agents specifically, one further point decides it: your agent framework needs an OpenAI-compatible endpoint with tool-calling support, and llama.cpp's llama-server --jinja provides exactly that (Β§9.3).

07Context and KV-cache engineering

For agents, the KV cache is where the war is fought: tool loops grow context without limit, and Figure 3's curve crosses every budget the rig has. The research community attacked this from four directions β€” paged allocation, KV quantization, eviction, and 2-bit compression β€” and all four shipped in the tools you can run today. This chapter is their evidence.

7.1 KV quantization: the cheapest context doubler

llama.cpp exposes KV precision with --cache-type-k / --cache-type-v (q8_0 and q4_0 are the useful tiers). The community's hands-on finding is consistent across model families: q8_0 KV costs essentially nothing in quality while halving the cache, and q4_0 halves it again with visible-but-tolerable degradation on summarization-heavy tasks. The Poor GPU Club thread (Β§10.1) shows the flag in live use β€” one user's Qwen3-30B-A3B run carries type_k/type_v q8_0 in its benchmark table, exactly because rung-4 models have no KV budget to waste.

KV precisionKB/token (Llama-3.1-8B)32K ctx costsCommunity verdict
f161284.3 GBDefault; the thing you turn off
q8_0642.1 GBThe agent default. Near-free quality-wise, doubles context
q4_0321.1 GBFor rung-3/4 models needing 32K+; expect softer recall of details

The one caveat the experiments surfaced: key and value tensors quantize differently well β€” the KIVI paper (below) traced this to per-channel vs per-token outlier structure β€” which is why llama.cpp lets you set K and V precision independently. Practical default: K at q8_0, V at q8_0 or q4_0.

7.2 The research record: StreamingLLM, H2O, KIVI, PagedAttention

paper StreamingLLM β€” attention sinks Xiao et al. Β· MIT Β· arXiv 2309.17453
Discovery
Evicting the first few tokens destroys quality; keeping 4 "sink" tokens + a sliding window enables infinite streams
Result
Stable perplexity at 4M+ tokens vs total collapse for plain sliding window

The paper everyone cites when their agent "forgets the instructions": early tokens receive a disproportionate share of attention mass (they act as sinks), so a cache that evicts them mid-conversation degrades sharply, while a cache that keeps a handful of them and slides a window over recent tokens keeps quality flat indefinitely. For low-resource agents the implication is direct β€” never let a sliding-window engine evict your system prompt, and when you compact context (Β§9.2), treat "keep the first N tokens" as a rule, not a nicety. llama.cpp's KV cache is not windowed by default (quality over memory), but several serving stacks and the Gemma-3/gpt-oss architectures use windowed attention natively β€” with exactly this failure mode when misused.

Archive verdict: the paper that named the failure mode every agent builder has personally experienced; its sink tokens rule is baked into Β§9's compaction recipe.
paper H2O β€” heavy-hitter eviction Zhang et al. Β· NeurIPS 2023 Β· arXiv 2306.14048

H2O showed that a small set of tokens accumulates most of the attention score mass during generation, and that evicting everything else β€” keeping the "heavy hitters" plus recent tokens β€” preserves generation quality with a cache 5–10Γ— smaller. It is the attention-score-based counterpart of PowerInfer's neuron-level finding, and the ancestor of the adaptive KV eviction now appearing in production engines. For the 8 GB reader it supplies the theoretical floor: most of your KV cache is dead weight, and tool-output tokens from three turns ago are the first weight to go.

Archive verdict: not directly exposed in llama.cpp today; its idea lives on in agent-level context compaction, which does the same thing one level up (Β§9.2).
paper KIVI β€” 2-bit KV without retraining Liu et al. Β· ICML 2024 Β· arXiv 2402.02750
Idea
Quantize keys per-channel, values per-token, keep a few hundred full-precision "residual" tokens
Result
4Γ— larger batch capacity; 2.35–3.47Γ— throughput on real workloads; accuracy preserved

KIVI nailed the asymmetry that Β§7.1's practical guidance hand-waves: key tensors have per-channel outliers (quantize along channels), value tensors have per-token outliers (quantize along tokens), and a short full-precision prefix absorbs the sinks StreamingLLM identified. Tuning-free, it compressed KV to 2-bit and measured 2.35–3.47Γ— throughput improvements in real serving workloads with up to 4Γ— more concurrent sequences. For this paper's rig, KIVI is the research-grade justification for what the community does pragmatically: aggressive KV quantization is sound at levels that would terrify a weight-quantization purist, because the cache stores history, not knowledge.

Archive verdict: the science behind q8/q4 KV flags; anyone building a custom stack should copy its asymmetric scheme verbatim.
paper PagedAttention / vLLM β€” KV as virtual memory Kwon et al. Β· SOSP 2023 Β· arXiv 2309.06180

Before PagedAttention, serving engines reserved contiguous KV blocks per sequence, wasting 60–80% of KV memory to internal fragmentation and over-reservation. Treating KV like OS pages β€” fixed blocks, on-demand allocation, a block table β€” cut waste to under 4%, enabling 2–4Γ— higher throughput and features (prefix sharing, copy-on-write) that matter enormously for agents: shared prefixes mean your agent's static system prompt + tool schemas are computed and stored once no matter how many turns reuse them. llama.cpp's unified KV management with -np parallel slots implements the same idea at smaller scale β€” and the official gpt-oss agent recipe (Β§10.2) uses it (-np 4) to serve parallel agent sessions.

Archive verdict: the infrastructure result the agent world silently depends on; use engines with paged/shared-prefix KV whenever you can.

08Speed levers that compound

Once placement (Β§4) and precision (Β§3, Β§7) are right, a second tier of optimizations buys the remaining 20–200%. The archive ranks them by measured payoff per unit of effort, and ends with the measurement discipline that keeps you honest while pulling them.

8.1 Seven levers, ranked by community payoff

#LeverFlag / methodTypical gainEvidence
1FlashAttention-fa on (now default in llama.cpp builds)10–25% tg, larger pp; less VRAMUniversal in every 2025 recipe incl. all Β§10 results
2Bigger prompt-processing batches-b 2048 -ub 20482–5Γ— faster prefillOfficial gpt-oss guide's universal flags; agents are prefill-heavy
3Parallel slots with shared prefix-np 2..4Near-linear for concurrent agent sessionsOfficial guide's agent recipe; PagedAttention lineage (Β§7.2)
4KV quantization--cache-type-k q8_0context 2Γ— (not speed)Β§7.1; Poor GPU Club tables
5Quant downgrade to fit more in VRAMIQ4_XS instead of Q4_K_XL+3–5 t/s via placementPoor GPU Club head-to-head (Β§10.1)
6Speculative decodingEAGLE-3 / Medusa / n-gram drafters2–3Γ— when applicableEAGLE: 3Γ— at 13B (below); llama.cpp PRs ongoing
7CPU-side tuningThread pinning, XMP/EXPO on, --no-mmap case-by-case5–20% on offload-heavy setupsgpt-oss-120b tuning writeups; Mixtral-offload paper's latency analysis
paper Speculative decoding β€” EAGLE and Medusa 2023–2025 Β· multiple venues
Idea
A tiny draft model proposes several tokens; the big model verifies them in one batched pass; accept-or-reject keeps outputs exact
EAGLE result
3Γ— vanilla at 13B; 2Γ— Lookahead; 1.6Γ— Medusa
2025 state
EAGLE-3 ~2–2.5Γ— in llama.cpp experiments; n-gram drafting ships

Speculative decoding is the one speed lever with a mathematical guarantee: the output distribution is provably identical to the big model's β€” the draft only proposes, the target always decides. Because decode is memory-bound (Β§1.2), verifying k tokens costs barely more than generating one, so every accepted draft token is nearly free. The catch on 8 GB rigs: the drafter competes for the same VRAM. That is why the biggest wins in the community came from n-gram drafters (no model at all β€” a lookup of your own recent text, remarkably effective on code and agentic loops where text repeats) and from EAGLE's tiny 1B-class heads on rung-1 setups. For agents specifically, the pattern-match structure of tool calls ("let me call search again...") is close to ideal drafter territory, and the 2025–26 engine work (vLLM shipping eagle/eagle3/medusa, llama.cpp discussions) is converging here fast.

Archive verdict: the highest-upside lever still in motion; check your engine's current speculative support before assuming it's absent β€” it moved fast.

8.2 Measuring honestly: the llama-bench discipline

Every credible experiment in this archive used the same loop, and Law 5 says you should internalize it before touching a single flag. The loop, plus the two traps the community documents most often:

bash β€” the measurement loop
# 1. baseline: one change at a time, same prompt lengths both sides
llama-bench -m model-Q4_K_M.gguf -fa 1 -p 512 -n 128

# 2. sweep the placement parameter (the one that matters most, Β§4)
llama-bench -m model.gguf -ngl 99 -ncmoe 24 -fa 1
llama-bench -m model.gguf -ngl 99 -ncmoe 28 -fa 1   # repeat until t/s peaks

# 3. watch VRAM *while* it runs β€” loading β‰  fitting (Windows lies)
nvidia-smi -l 1          # Linux; on Windows: Task Manager > GPU > "GPU Memory"

# 4. write it down. The Poor GPU Club thread is literally this loop, in public.
Trap 1 β€” benchmark speed β‰  server speed

The Poor GPU Club author's own note: llama-bench reported 31–38 t/s, but llama-server with a 32K context window ran somewhat slower, because the server pays for the KV allocation and the traffic. Always re-measure inside the deployment shape you'll actually run.

Trap 2 β€” pp and tg are different diseases

pp (prompt processing, compute-bound) and tg (token generation, bandwidth-bound) respond to opposite medicine β€” bigger ubatch helps pp and can hurt tg's memory budget. A rig can be fast at one and miserable at the other; agents need both, so always record pp512 and tg128 together, exactly as llama-bench prints them.

09The agent stack on 8 GB

Everything before this chapter was about serving a model well. Agents change the workload: context grows every turn, tool outputs arrive faster than the model can forget them, and the failure mode shifts from "slow" to "OOM mid-task, at turn 12, after twenty minutes of work." This chapter is the discipline that prevents that.

9.1 The memory anatomy of an agent loop

An agent turn appends four things to context: the model's reasoning, the tool call it emitted, the tool's raw output, and the framework's bookkeeping (tool schemas ride along in the system prompt from turn 0). A representative loop β€” one tool call per turn, moderately verbose tools β€” adds ~0.8K tokens per turn, and that compounds:

0 1 2 3 4 5 6 7 8 9 10 11 12 agent turn 0 5 10 15 20 25 30 35 context size (thousand tokens) 32K tokens β€” ceiling for a comfortable 8 GB setup compaction checkpoint (10.6K): summarize + drop old tool output Why agents are the hardest workload: context growth per agent turn (representative tool-using loop: ~0.8K new tokens per turn) system prompt + tool schemas tool results / RAG chunks conversation + agent reasoning
Figure 7.Context growth in a tool-using agent loop (illustrative model calibrated to community-observed loops: 1.5K static prompt + tool schemas, ~0.8K appended per turn). The green dotted line marks the compaction checkpoint from Β§9.2. Agents don't run out of memory at load time β€” they run out during the task, which is what makes KV discipline (Β§7) and compaction (below) load-bearing rather than optional.

Reading the figure against the rig's budgets produces the three numbers every 8 GB agent operator should know cold: 16K context is the comfortable default (q8 KV, ~1 GB, leaves headroom), 32K is the practical ceiling with q8 KV on rung-4 models, and past 32K you are trading model rungs for context β€” a smaller model with more context usually beats a bigger model that crashes. The Figure-3 curve is exponential in your patience: every extra turn costs the same tokens but progressively fills the only pool that matters.

9.2 Patterns that survived contact

Four agent-design patterns recur across the successful low-resource builds in this archive. They are ordered by leverage:

Pattern 1 β€” Context compaction (the load-bearing one)

When context crosses a threshold (the green line in Figure 7), summarize the oldest turns into a compact running brief, drop verbatim tool outputs, and keep four things verbatim: the original task statement, the attention-sink prefix (the system prompt's first tokens β€” Β§7.2's StreamingLLM finding), the latest two turns, and any facts the task depends on. Implemented in ~30 lines in the agent harness (not the model), it converts an exponential context curve into a sawtooth and is the difference between 15-turn tasks that finish and ones that die. Every serious agent framework of 2024–25 grew a compactor for exactly this reason.

Pattern 2 β€” Tool-result triage at the boundary

Never paste raw tool output into context. A web search returns 4K tokens; the model needs 200 of them. The archive's working pattern is a fixed triage at the tool boundary β€” head/tail truncation, structural extraction (parse the JSON, keep the fields the task needs), or a cheap summarize pass on a rung-1 model. This is the agent-side twin of KV quantization: it shrinks the bytes that ever enter the cache.

Pattern 3 β€” One orchestrator, cheap specialists

The rung-4 MoE orchestrates; a rung-0/1 dense model (often CPU-resident, Β§6.2) handles utility calls β€” rerank, schema-fix, summarize. The two-model split works on the 8 GB rig precisely because the specialist can live in the 32 GB RAM pool where its 5–10 t/s is irrelevant to latency-critical paths, and because the orchestrator's VRAM share is never contested mid-task.

Pattern 4 β€” Retry with degradation, never crash

OOM at turn 12 loses the task. The working pattern: catch the server's OOM/timeout error, halve the context window, compact harder, reload, and resume from the brief. llama.cpp's server returns clean errors on failed allocations, which makes this pattern mechanical β€” and it converts the rig's hard memory ceiling into a soft one.

9.3 A reference stack, end to end

Here is the stack the archive's evidence points to, in one diagram-shaped paragraph and one runnable artifact. Serving: llama.cpp llama-server with a rung-4 model, --jinja for tool-call templates, expert offload tuned per Β§8's sweep, q8_0 KV, 16–32K context, FlashAttention on. Protocol: the server's OpenAI-compatible endpoint, so any standard framework can drive it. Agent harness: whatever you like β€” the community's experiments span LangGraph, claude-code-style CLI loops, and 300-line custom harnesses β€” with Patterns 1–4 implemented at the harness level. Observability: nvidia-smi in a side terminal, always (Law 5).

The minimal version, complete and runnable, is short enough to be its own proof that "agent" need not mean "framework":

python β€” a 60-line agent loop against llama-server
import json, requests

SERVER = "http://127.0.0.1:8080/v1/chat/completions"
TOOLS = [{
    "type": "function", "function": {
        "name": "read_file",
        "description": "Read a text file from disk",
        "parameters": {"type": "object",
            "properties": {"path": {"type": "string"}},
            "required": ["path"]}}}
# triage at the boundary: Pattern 2 β€” tools may return at most this many chars
MAX_TOOL_CHARS = 1500

def run_tool(name, args):
    if name == "read_file":
        text = open(args["path"], errors="replace").read()
        return text[:MAX_TOOL_CHARS] + ("...[truncated]" if len(text) > MAX_TOOL_CHARS else "")
    return "unknown tool"

def agent(task, max_turns=12):
    msgs = [{"role": "system", "content":
             "You are a precise agent. Use tools. Be terse."},
            {"role": "user", "content": task}]
    for turn in range(max_turns):
        r = requests.post(SERVER, json={"messages": msgs,
            "tools": TOOLS, "temperature": 0.3}).json()
        m = r["choices"][0]["message"]
        msgs.append(m)
        if not m.get("tool_calls"):
            return m["content"]          # final answer
        for tc in m["tool_calls"]:   # execute, append results
            out = run_tool(tc["function"]["name"],
                           json.loads(tc["function"]["arguments"]))
            msgs.append({"role": "tool",
                         "tool_call_id": tc["id"], "content": out})
    return "max turns reached"

if __name__ == "__main__":
    print(agent("Read config.yaml in this directory and list every API key name it defines."))

Swap in your task and tools; the loop's shape is the production pattern minus compaction (add Pattern 1 by summarizing msgs[2:-4] when len(json.dumps(msgs)) crosses your threshold β€” the exact checkpoint logic from Figure 7's green line).

What "managing a complex task" looks like on this rig

The reader's goal, made concrete by this stack: a 30B-class orchestrator at 20–34 t/s with 32K of disciplined context, cheap utility calls, tool outputs triaged at the boundary, and a sawtooth context curve instead of an explosion. That is a machine that reads your codebase, plans a change, edits files, runs the tests, and reports back β€” the "complex task inside a low-resource PC" this paper promised to make possible.

10Case studies: the experiments, in their own words

Three experiments deserve to be read as whole stories rather than as data points, because each one demonstrates the full loop β€” hypothesis, sweep, measurement, community iteration β€” that this paper wants its readers to be able to run.

10.1 The Poor GPU Club: 8 GB VRAM versus two MoE flagships

community β€œPoor GPU Club: 8GB VRAM β€” Qwen3-30B-A3B & gpt-oss-20b t/s with llama.cpp” r/LocalLLaMA Β· post-mortem reproduced in full below
Rig
RTX 3070 8 GB Β· 32 GB+ RAM Β· Windows
Method
llama-bench sweeps of --n-cpu-moe per model/quant
Headline
31–38 t/s day-one, tuned across three quants

The author's stated goal β€” "day 1 attempt" at getting flagship MoE models usefully fast on an 8 GB card β€” and their posted results, exactly as measured with llama-bench:

Model & quantFileCommand coret/s
Qwen3-30B-A3B UD-Q4_K_XL~18.6 GB-ngl 99 -ncmoe 29 -fa 131
Qwen3-30B-A3B IQ4_XS~16.8 GB-ngl 99 -ncmoe 28 -fa 134
gpt-oss-20b MXFP411.3 GB-ngl 99 -ncmoe 10 -fa 138

Read as an experiment, the thread is a textbook execution of the laws from Β§1: (a) placement beats quant β€” moving from Q4_K_XL to the slightly smaller IQ4_XS let one more MoE layer's experts fit in VRAM, worth +3 t/s at equal quality; (b) the ncmoe values (~10 for a 21B model, ~28 for a 30B) are exactly where the Figure-5 curve says an 8 GB card should land; (c) honest reporting β€” the author immediately notes server speeds run lower than bench speeds at 32K context (Trap 1, Β§8.2) and that previous 8 GB owners reported "only 20+ t/s," framing their own 31–38 as the state of the art to beat; (d) community iteration β€” commenters added their own rigs, including a second 8 GB-class machine reproducing 20 t/s on Qwen3-Coder-30B-A3B with --n-cpu-moe 34 and 26 t/s on gpt-oss with --n-cpu-moe 13 (150–200 t/s prompt processing with -ub 1024 -b 1024), and a 64 GB-RAM reader running gpt-oss-120b at 16 t/s β€” rung 5 of the ladder, on this class of machine.

Archive verdict: the definitive community proof of this paper's thesis. A 30.5B-parameter agent-capable model at 31–34 t/s, and a 120B at 16 t/s, on gaming hardware β€” via placement (Β§4.2), quantization (Β§3.1), FlashAttention, and measurement discipline (Β§8.2), nothing else.

10.2 The official 8 GB recipe: llama.cpp's gpt-oss guide

The llama.cpp team's gpt-oss launch guide (source of Β§5's cross-silicon table) is the "official" counterpart to the Poor GPU Club: same model, same engine, sanctioned flags per hardware tier. Its 8 GB-relevant guidance, condensed:

TierGuidance
> 64 GB VRAMOffload everything, full context: --ctx-size 0, no compromises
16–24 GB VRAMgpt-oss-20b fully in VRAM; or 120b with a few expert layers on CPU
< 16 GB VRAM (this paper's rig)Run the whole model on GPU except expert tensors: -ngl 99 --n-cpu-moe 16–22 β€” named example: RTX 2060 8 GB; even the 120B works with --n-cpu-moe 35 -c 32768
8 GB unified memory (Macs)Cannot run gpt-oss β€” the pool is too small once the OS eats its share (Β§5.2's moral)
Agent servingFor coding agents: --ctx-size 0 --jinja -ub 2048 -b 2048; add -np 4 parallel slots for agents that benefit (with the guide's caveat: slots cost memory)

One further warning from the guide deserves verbatim status, because it is the single most common way 8 GB users silently destroy their performance β€” Windows will over-commit VRAM and swap instead of failing:

From the official guide, unedited in substance

"On Windows it is possible to allocate more VRAM than available, and the result will be slow swapping to RAM and very bad performance. Just because the model loads without errors, it doesn't mean you have enough VRAM... A good way to avoid this is to look at the 'GPU Memory' in Task Manager and check that it does not exceed the GPU VRAM." The guide's own calibration example on a 32 GB card: --n-cpu-moe 21 β†’ GPU memory under 32 GB (good) vs --n-cpu-moe 20 β†’ over 32 GB (silent catastrophe). One expert layer is the difference.

10.3 Four Raspberry Pis: the floor of the experiment

community Qwen3-30B-A3B on a 4 Γ— Raspberry Pi 5 cluster 2025 Β· widely circulated benchmark
Hardware
4 Γ— Pi 5 (8 GB), tensor-parallel llama.cpp RPC
Result
13 t/s on a 30.5B MoE model
Context
single Pi-class board on same model: ~8 t/s

Four $80 boards, strung with llama.cpp's RPC backend into one virtual 32 GB / ~68 GB/s machine, generating a frontier-adjacent 30B model at reading speed. As an engineering artifact it is glorious; as evidence it closes the loop on this paper's physics: the cluster works because the model is MoE with 3.3B active parameters (the per-token working set fits what the cluster can stream), and it caps out at 13 t/s because four LPDDR4X channels are still only ~68 GB/s β€” the bandwidth law, obeyed to the decimal. If the placement principles hold at 17 GB/s (this) and at 448 GB/s (Β§10.1), they hold everywhere between.

Archive verdict: the boundary marker of the field: below ~10 t/s agents remain possible but joyless; the cluster proves the ceiling is bandwidth, never parameter count.

11The playbook: from zero to a running agent

Everything in the archive, compressed into one afternoon. Follow the steps in order; each one ends in something measurable, and every command is the exact shape used by the experiments you just read.

11.1 The steps

  1. Establish the baseline machine. Confirm 32 GB RAM, dual-channel populated, XMP/EXPO enabled (worth 5–20% on offload-heavy setups, Β§8.1 lever 7). Update the GPU driver. Close the browser. Open a terminal with nvidia-smi -l 1 and leave it running β€” this is your truth-teller for the rest of the session.
  2. Install llama.cpp with CUDA. Prebuilt release binary, or build from source with -DGGML_CUDA=ON. Verify with llama-server --version and a CUDA device listing on startup.
  3. Download a rung-4 model and its smaller sibling. From the ladder: Qwen3-30B-A3B IQ4_XS (or UD-Q4_K_XL) plus a Q4_K_M 8B for utilities. Use the official GGUF repos (ggml-org, Unsloth, bartowski all publish calibrated quants).
  4. Sweep the placement. Run the Β§8.2 llama-bench loop: -ngl 99 -ncmoe 24, then 26, 28, 30… watch t/s climb then fall as VRAM pressure builds, and watch nvidia-smi to stay under ~7.4 GB. Keep the peak. This is the single highest-value hour in the playbook β€” the Poor GPU Club's 31β†’34 t/s came from exactly this step.
  5. Start the server, tuned. The recipe below. Verify with one chat completion and one tool call from the Β§9.3 loop before building anything larger.
  6. Wire the agent harness. The 60-line loop from Β§9.3, or your framework of choice pointed at http://127.0.0.1:8080/v1. Implement Patterns 1 and 2 (compaction + triage) before your first long task β€” retrofitting them after a mid-task OOM is how people learn Law 3 the hard way.
  7. Run a real task end-to-end. Something honest: "read this repo, find the bug the test describes, fix it, run the tests." Watch the context sawtooth, watch VRAM, and record t/s at turn 1 vs turn 10. If turn 10 is much slower, your context discipline slipped β€” that diagnosis, not hardware, is the usual finding.

11.2 Copy-paste recipes, annotated

bash β€” recipe A: the agent server (rung 4, the daily driver)
# Qwen3-30B-A3B as the orchestrating agent on 8 GB VRAM + 32 GB RAM
#   -ngl 99       : attention + shared layers fully on GPU
#   -ncmoe 28     : expert tensors for 28 of 48 MoE layers live in RAM (SWEEP THIS, Β§11.1 step 4)
#   -fa           : FlashAttention (lever 1)
#   --cache-type-k/v q8_0 : halves KV so 32K context fits (Β§7.1)
#   --jinja       : native tool-calling template for the agent loop
llama-server -m Qwen3-30B-A3B-IQ4_XS.gguf \
  -ngl 99 -ncmoe 28 -fa 1 \
  -c 32768 -ctk q8_0 -ctv q8_0 \
  -b 2048 -ub 2048 --jinja \
  --host 127.0.0.1 --port 8080
bash β€” recipe B: gpt-oss-20b, the one-model alternative
# Official-guide-derived 8 GB configuration (Β§10.2):
llama-server -hf ggml-org/gpt-oss-20b-GGUF \
  --ctx-size 32768 --jinja -ub 2048 -b 2048 \
  -ngl 99 --n-cpu-moe 16 -fa 1
# n-cpu-moe 16 buys speed (fewer experts on CPU) at the cost of context;
# n-cpu-moe 22 buys full context at ~2/3 of the speed. Pick per task.
bash β€” recipe C: CPU-side utility model (Pattern 3)
# The rung-1 specialist on CPU only β€” 32 GB RAM runs it at ~8-12 t/s
# while the GPU stays fully committed to the orchestrator.
llama-server -m llama-3.1-8b-Q4_K_M.gguf -ngl 0 \
  -c 8192 -t $(nproc) --host 127.0.0.1 --port 8081
bash β€” recipe D: batch document ingestion (the FlexGen shape, Β§4.3)
# Throughput, not latency: huge batches, everything prompt-processing-friendly
llama-server -m model.gguf -ngl 99 -ncmoe 28 -fa 1 \
  -c 32768 -b 4096 -ub 4096 --jinja
# pair with -np 2..4 parallel slots when the framework can use them (Β§8.1 lever 3)

11.3 The verification checklist

CheckHowPasses when
VRAM headroomnvidia-smi during load + first turnsUnder ~7.4 GB used; no growth across turns
Placement optimumllama-bench ncmoe sweep tableYou know your peak t/s and the ncmoe that produced it
Tool-calling worksΒ§9.3 loop on a trivial taskModel emits a valid tool call, harness executes it, loop closes
Context sawtoothLog context size per turnSize oscillates under your threshold; no monotonic climb
Latency honestyt/s at turn 1 vs turn 10Within ~25% β€” otherwise re-check KV type and compaction
OOM resilienceForce a tiny context; watch behaviorPattern 4 catches, compacts, resumes β€” task survives
Definition of done

All six checks pass, and your agent has completed one non-trivial real task on the 8 GB machine β€” planning, calling tools, and finishing without manual babysitting. You now know more about low-resource inference than most of the people posting benchmarks, because you can reproduce all of Chapter 4's experiments on demand.

12Troubleshooting: the failure catalog

Every failure below is one the archive documents someone hitting, diagnosing, and fixing. The table is organized by symptom, because that is what you will have in hand when it happens.

12.1 Out-of-memory and crash matrix

SymptomReal causeFix
Loads fine, then CUDA OOM at first long promptKV cache sized for full context is allocated lazily/deferred; the prompt triggered it (Law 3)Reduce -c; add -ctk q8_0 -ctv q8_0; smaller ubatch
Model "loads," generation crawls at 1–3 t/sWindows VRAM over-commit β†’ silent swap to RAM (Β§10.2's official warning)Watch Task Manager GPU memory; raise --n-cpu-moe until under VRAM; one expert layer can be the whole difference
Crash mid-agent-task after N turnsContext grew past allocation (Figure 7's red line)Pattern 1 compaction; enforce a hard context budget in the harness
OOM on load even though "it should fit"Unbudgeted overhead: CUDA context, compute buffer scales with -b, second model still residentAudit against Β§2.2's four rows; drop -b to 1024; verify one model at a time
System RAM exhausted (Linux OOM-killer takes the server)Expert offload + --no-mmap + big context exceeds 32 GBLet mmap do its job (drop --no-mmap); lower ncmoe; smaller context
Fine on short chats, degrades badly past ~8K tokensPrompt-processing batch too small, or KV in f16 (Β§7.1)-ub 2048; quantize KV; check FlashAttention is on

12.2 "Why is it slow?" β€” the decision path

diagnose
Measure first llama-bench pp512 + tg128 on the exact file and flags. Slow in bench too? β†’ hardware/placement. Fast in bench, slow in server? β†’ context or traffic.
tg slow, pp fine Placement problem β€” weights on the wrong side of the wire. β†’ ncmoe sweep, quant downgrade to fit more in VRAM (Poor GPU Club's +3–5 t/s move).
pp slow, tg fine Batch problem β€” prefill starved. β†’ -b 2048 -ub 2048, FlashAttention on; for batch jobs go 4096.
Both slow from turn 8+ Context problem β€” KV pressure. β†’ q8_0 KV, compaction checkpoint, triage tool outputs harder.
Everything slower than threads suggest CPU-side: single-channel RAM, XMP off, thermal throttle, or Windows GPU scheduling.
Still stuck Post your llama-bench table + nvidia-smi screenshot + exact command. The Poor GPU Club will recognize its own.
The meta-rule of troubleshooting this rig

Four suspects, always the same four: placement (weights on the wrong pool), context (KV grew past the budget), batching (pp/tg confusion), overcommit (Windows lying about fit). Every failure in the catalog reduces to one of them, and each has a one-flag first response. Diagnosis is measurement (Β§8.2); never guess at flags β€” sweep them.

13Glossary

Working definitions as used in this paper β€” biased toward the operational meaning on an 8 GB rig rather than the textbook one.

Active parameters
The fraction of an MoE model's weights that participate in a given token's computation (gpt-oss-20b: 3.6B of 21B). Along with quantization, the master variable of the bandwidth law.
Attention sink
Early-sequence tokens that absorb disproportionate attention mass; evicting them from cache collapses quality (StreamingLLM). Reason your agent's system prompt prefix is sacred.
CPU offload (expert) β€” --n-cpu-moe
Architecture B: keep attention/shared weights in VRAM, expert tensors in system RAM. The 2024–25 answer to small VRAM.
CPU offload (layer) β€” --n-gpu-layers
Architecture A: the first N transformer layers on GPU, the rest on CPU. Simple, scales poorly (Β§4.1).
FlashAttention
Fused, memory-lean attention kernel; ~free speed and VRAM on every modern build. If your engine has a flag for it, it should be on.
GGUF / K-quants / I-quants
llama.cpp's model container and its quant families. K-quants (Q4_K_M…) are block-scaled grids; I-quants (IQ4_XS…) add importance-matrix calibration for better quality per bit at low widths.
GQA (grouped-query attention)
Sharing K/V heads across query heads β€” the architecture change that cut KV-per-token ~4Γ— on modern 7–9B models. Assumed by every current model in the ladder.
KV cache
Per-token key/value memory saved so past tokens aren't recomputed; grows linearly with context (Β§2.3's formula). The agent-relevant memory cost.
MoE (mixture of experts)
Architecture with many specialist FFN blocks ("experts") and a router selecting a few per token. Large total knowledge, small per-token compute β€” the enabling trick of low-VRAM inference.
MXFP4
The 4-bit microscaling format gpt-oss models ship in natively (block-scaled, hardware-friendly). A vendor-grade answer to "which 4-bit."
PagedAttention
Treating KV memory like OS pages β€” on-demand, shareable, near-zero waste (vLLM). Why parallel agent slots are affordable.
pp / tg (prompt processing / token generation)
The two halves of inference latency: compute-bound prefill (the prompt read) and bandwidth-bound decode (the answer). Different bottlenecks, different medicine.
QAT (quantization-aware training)
Training with quantization in the loop so 4-bit weights are compensated at the source β€” Gemma-3-12B QAT's route onto 8 GB cards at 12B quality.
Speculative decoding
A small drafter proposes tokens; the big model verifies in one batched pass. Output-exact, 2–3Γ— where it applies (Β§8.1).
Unified memory
One physical pool shared by CPU and GPU (Apple M-series, integrated GPUs). No PCIe wire β€” bandwidth is honest and capacity is shared with the OS.
VRAM over-commit
Windows allocating more GPU memory than exists and silently swapping β€” the "it loaded, why is it 2 t/s" trap. Diagnosed only by watching real usage.

14Annotated sources

Every experiment reproduced in this paper, with its origin. Papers are listed by venue/arXiv; community and official sources by platform. Numbers were transcribed from these sources during August 2025–2026 research for this edition; where a source thread contains multiple rigs, the paper's tables say which one.

Peer-reviewed systems papers

[1]
PowerInfer: Fast Large Language Model Serving with a Consumer-grade GPU. Song, Mi, Xie, Chen (SJTU). arXiv:2312.12456. Hot-neuron preloading, sparse CPU operators, up to 11.69Γ— vs llama.cpp on one RTX 4090. arxiv.org/abs/2312.12456
[2]
FlexGen: High-Throughput Generative Inference of Large Language Models with a Single GPU. Sheng et al. ICML 2023. arXiv:2303.06865. Block-scheduled offload; OPT-175B on one 16 GB GPU. arxiv.org/abs/2303.06865
[3]
Fast Inference of Mixture-of-Experts Language Models with Offloading. Eliseev & Mazur. arXiv:2312.17238. LRU expert cache + speculative prefetch on an 8 GB laptop GPU; 2–3Γ— over naive offload. arxiv.org/abs/2312.17238
[4]
Fiddler: CPU-GPU Orchestration for Fast Inference of Mixture-of-Experts Models. Kamahori et al. ICLR 2025 (efeslab). arXiv:2402.07033. Run experts on CPU where the weights live; Mixtral-8x22B on one 8 GB GPU, up to ~3.5Γ— vs [3]. arxiv.org/abs/2402.07033 Β· github.com/efeslab/fiddler
[5]
Efficient Memory Management for LLM Serving with PagedAttention (vLLM). Kwon et al. SOSP 2023. arXiv:2309.06180. KV waste 60–80% β†’ under 4%; 2–4Γ— throughput. arxiv.org/abs/2309.06180
[6]
KIVI: A Tuning-Free Asymmetric 2-bit Quantization for KV Cache. Liu et al. ICML 2024. arXiv:2402.02750. 2-bit KV with asymmetric K/V schemes; 2.35–3.47Γ— throughput, 4Γ— batch capacity. arxiv.org/abs/2402.02750
[7]
Efficient Streaming Language Models with Attention Sinks (StreamingLLM). Xiao et al. arXiv:2309.17453. Sink tokens + sliding window; stable quality at millions of tokens. arxiv.org/abs/2309.17453
[8]
H2O: Heavy-Hitter Oracle for Efficient Generative Inference. Zhang et al. NeurIPS 2023. arXiv:2306.14048. Attention-score-guided KV eviction with 5–10Γ— cache reduction. arxiv.org/abs/2306.14048
[9]
AWQ: Activation-aware Weight Quantization. Lin et al. arXiv:2306.00978. Protects salient channels via per-channel scaling; best-in-class 4-bit quality in Β§3.2's tables. arxiv.org/abs/2306.00978
[10]
Half-Quadratic Quantization (HQQ). Novikov et al. arXiv:2306.09748-family (and follow-ups). Calibration-free 4/8-bit; source of the cross-method perplexity table in Β§3.2. mobiusml.github.io/hqq_blog
[11]
EAGLE / EAGLE-3 speculative decoding. Li et al. arXiv:2401.15077 and follow-ups; sites.google.com/view/eagle-llm. 3Γ— vanilla at 13B; 2–2.5Γ— in 2025 llama.cpp discussions. arxiv.org/abs/2401.15077

Official benchmarks and guides

[12]
Guide: running gpt-oss with llama.cpp. ggml-org discussion #15396, Aug 2025. Cross-silicon llama-bench set (M-series, RTX tiers, AMD), the <16 GB VRAM recipes, agent-serving flags, and the VRAM-overcommit warning quoted in Β§10.2. github.com/ggml-org/llama.cpp/discussions/15396
[13]
Gemma 3 QAT model release. Google Developers Blog, April 2025. 12B at <8 GB VRAM, RTX 4060-laptop named; "similar benchmark performance to bf16 at 4-bit." developers.googleblog.com/en/gemma-3-quantization-aware-training
[14]
Qwen speed benchmark tables. Qwen documentation β€” per-quant throughput reference for the ladder's rung-4 models. qwen.readthedocs.io β€” Speed Benchmark

Community experiments

[15]
β€œPoor GPU Club: 8GB VRAM β€” Qwen3-30B-A3B & gpt-oss-20b t/s with llama.cpp.” r/LocalLLaMA. The 31/34/38 t/s sweep and the follow-up rigs (20 t/s Qwen3-Coder with ncmoe 34; 26 t/s gpt-oss with ncmoe 13; 16 t/s gpt-oss-120b on 64 GB RAM). reddit.com/r/LocalLLaMA/comments/1nyxmci
[16]
The --n-cpu-moe sweep on gpt-oss-20b. llama.cpp discussion #15396 reply thread (collaborator measurements): 60/38/26 t/s at ncmoe 4/8/16 with VRAM readouts. github.com/ggml-org/llama.cpp/discussions/15396
[17]
LLaMA performance benchmarking with llama.cpp on NVIDIA GPUs. kubito.dev β€” the 8 GB RTX 3070 Ti partial-offload dataset behind Β§4.1. kubito.dev/posts/llama-nvidia-3070-ti-benchmarks
[18]
Detailed performance numbers and Q&A for llama.cpp. r/LocalLLaMA thread 13h7cqe β€” the classic partial-offload dataset ("10Γ— if you can fit half the layers" and its corrections). reddit.com/r/LocalLLaMA/comments/13h7cqe
[19]
Qwen3-30B-A3B hits 13 token/s on 4Γ— Raspberry Pi 5. Community cluster benchmark, widely circulated 2025; single-board runs of the same model at ~8 t/s. news.ycombinator.com/item?id=45148237
[20]
Pi-5 LLM benchmarking series. wolfpaulus.com (BLIS vs OpenBLAS: 2.73 vs 2.34 t/s) and stratosphereips.org (llama.cpp vs Ollama, 10–20% engine gap). wolfpaulus.com/local_llama Β· stratosphereips.org
[21]
Comparing quantized performance in Llama models. GreaterWrong/LessWrong post β€” the Llama-3-8B GGUF perplexity ladder and the Llama-3-8B-Instruct MMLU/WMDP cross-method run reproduced in Β§3. greaterwrong.com/posts/qmPXQbyYA66DuJbht
[22]
Smaller Gemma3 QAT versions β€” community verification. r/LocalLLaMA thread on 12B QAT under 8 GB (2.5K context stock; more with -fa and q8 KV). reddit.com/r/LocalLLaMA/comments/1jsq1so
[23]
Optimizing gpt-oss-120b on consumer hardware. carteakey.dev β€” CPU pinning, XMP, and VRAM fitting on a 4070; lever-7 evidence for Β§8.1. carteakey.dev/blog/local-inference/optimizing-gpt-oss-120b-local-inference

A note on data hygiene: figures 1–4 and 6–7 are plotted from the numbers above; Figure 5 mixes measured points with one estimated anchor (the full-GPU tier of a 24 GB card), labeled as such in its caption. Where sources disagreed (e.g., MLX vs llama.cpp Mac speeds), the disagreement itself was reported rather than averaged away. Reader-measured numbers will drift from these as engines and drivers improve β€” the archive's claims are about the shape of the relationships, which has been stable since 2023.

The 8 GB Vanguard β€” Edition 2, the Experiment Archive.
A single-file research paper. Works offline; print it and it becomes a book.
Set in the system fonts you already have. Figures rendered as inline SVG from the cited datasets.
Laws: five. Experiments: twenty-three. Excuses: zero.

Related Posts

Maximum Capability from Minimum Silicon

A book-length engineering research paper on maximizing 8 GB GPU + 32 GB RAM workstations for AI agent workloads.

Read more β†’

GGUF vs EXL2 vs AWQ vs GPTQ

Master quantization formats for local AI: precision, speed, VRAM trade-offs.

Read more β†’

GPU & CPU Inference Troubleshooting

Complete troubleshooting guide for inference issues β€” OOM, slow tok/s, KV cache pressure.

Read more β†’

About the Author

Hussain Nazary is a software developer specializing in local AI deployment and the creator of GGUF Loader, an open-source tool for running GGUF models locally. This analysis is part of Local AI Zone's ongoing coverage of open-weight language models and practical deployment strategies.

Contact: GitHub | Consulting Services

Last Updated: August 26, 2026 | Version 1.0