LLMs on Consumer Hardware — Part 2: Prefill and the Failure of the AI PC
Part 1 established the hardware, the runner, and the primary model. This entry covers what governs inference on that hardware — the two phases of inference, the cost of long context, and the cost of loading a model from disk — and compares the local machines against a free-tier cloud model. The two phases of inference Inference has two phases. Prefill processes the input prompt before any output appears; it is compute-bound and wants a GPU. Generation produces output tokens one at a time and is bound by memory bandwidth. Casual use is almost all generation and hides the difference; the cost of prefill surfaces only when prompts grow large. The machines, and how they were measured Machine CPU / RAM GPU (VRAM) Storage (read) Prefill (tok/s) Gen (tok/s) Load (18 GB) Primary desktop 5950X / ~80 GB DDR4 RX 6900XT (16 GB) NVMe (~2.1 GB/s) 360 18.3 8.4s Secondary box 5600G / 32 GB DDR4 GTX 1060 (6 GB) SATA SSD (~0.35 GB/s) 253 17.1 50.6s Laptop 8840U / 32 GB DDR5 Radeon 780M (none) NVMe (~2.4 GB/s) 20 10.0 7.5s All inference figures come from a controlled run: the same model (Gemma 4 26B, 18 GB) on each machine, a unique random prefix per prompt to defeat caching, a fixed 8,192-token context, warm, on an identical ~6,855-token prompt (generation timed over a 200-token output). Two things stand out. Prefill varies about eighteen-fold across the machines (360 to 20 tok/s) while generation varies less than twofold (18.3 to 10.0), and prefill is what dominates large-prompt workloads — so a machine can look fine on generation yet be useless in practice. Model-load time, separately, is set by storage rather than compute: the secondary box's budget SATA SSDs load the 18 GB model in 50 seconds against eight on NVMe, which turns a cold request into a minute-long stall. Secondary box Request time Warm (model resident) ~4s Cold (model reload) ~54s If the model is allowed to unload between calls, every call silently pays that reload — a real source of intermittent timeouts. The fix is