●  Ran in a home lab, Sep 1–5 2026 · GLM-5.3-Flash · EXL3 TR3 4bpw

320 billion parameters.Two desktop boxes.

GLM-5.3-Flash is a 320B mixture-of-experts model. It has no business running next to a router in a spare room. It does anyway — split across two NVIDIA DGX Sparks wired together with a 200-gigabit cable, quantized to four bits, and taught to draft its own tokens. Every number on this page was measured on that machine on Sep 5, 2026, the day before it was stood down.

0
Parameters
0
Weights on disk
0
KV cache tokens
0
Fastest reply
01 — The machine

Two Sparks, one cable,
one model split down the middle.

A single DGX Spark has 128 GB of unified memory. The quantized model needs 164 GB. So the model gets cut in half — every attention head and every expert layer is split across both machines, and the two halves talk to each other on every single token.

sparky1 · 10.100.128.1 GB10 · 128 GB unified TP rank 0 · 82.03 GiB weights agent lane :8891 · schedutil · 3.3 GHz cap sparky2 · 10.100.128.2 GB10 · 128 GB unified TP rank 1 · 82.03 GiB weights coding lane :8892 ConnectX-7 · 200 Gb/s · RoCE all-reduce, every token
← swipe to see both machines →

Why two

164 GB of weights will not fit in 128 GB. Tensor parallelism splits each layer's matrices column-wise, so each box stores and computes exactly half.

Why the cable matters

Both halves must be recombined at every layer. Over ordinary ethernet that sync dominates. The 200 Gb ConnectX link makes it small enough to ignore.

What you get

A 756,736-token KV cache and a 262,144-token context window — long enough to hold an entire codebase in one conversation.

02 — Making it fit

Four bits, chosen carefully.

Quantization is where most home-lab attempts quietly lose the model's intelligence. The honest way to choose is KL divergence against the full-precision model: how far the compressed model's probability distribution drifts from the original. Lower is better. Click a rung.

formatmemory footprinttotal
BF16full precision · reference
640 GB
FP88-bit · KLD 0.0206
328 GB
EXL3 TR3 4bpwtrellis-coded · KLD 0.0246
164 GB
NVFP44-bit native · KLD 0.0605
181 GB

The memory bill

Weights, per Spark82.03 GiB
Weights, total164 GB
GPU memory utilization0.87
KV cache756,736 tokens
Max context per request262,144 tokens
Concurrent full-context requests2.89×

Cold start is real

Loading 164 GB of weights off disk and warming CUDA graphs is not instant. Plan for it, and never let a watchdog restart the engine casually.

Model load344 s
Engine init, KV cache, warmup78 s
Container start to first token~8 min
03 — Two lanes, one brain

The same model, wearing
two different personalities.

A voice assistant wants an answer in under a second. An autonomous coding agent wants deep reasoning and does not care if it waits a minute. Running two models would need memory nobody has. Instead one engine serves two ports with different priorities and different reasoning budgets — and the scheduler always lets the human jump the queue.

Agent lane :8891

  • Scheduler priority 0 — always served first
  • Reasoning effort low, thinking off
  • For voice, chat, home automation
  • Measured today: 0.63 – 1.6 s to a reply

Coding lane :8892

  • Scheduler priority 10 — yields to the human
  • Reasoning effort high, thinking on
  • For autonomous build loops and refactors
  • Runs for minutes; nobody is waiting
← swipe to follow a request →
Watch the cyan request cut the line. That is --scheduling-policy priority.

The trap that cost a week

GLM-5.3 defaults reasoning_effort to max. Not medium. Max. A one-line question took 33 seconds and often returned an empty message, because the model spent its whole token budget thinking and had nothing left to say. Setting it explicitly per lane made the assistant 25× faster with no loss of quality on short questions.

# every request, on both lanes — never rely on the default
{
  "model": "brandonmusic/GLM-5.3-Flash-tr3-4bpw",
  "messages": [...],
  "chat_template_kwargs": {
    "reasoning_effort": "low",   // "high" on the coding lane
    "thinking": false        // true on the coding lane
  }
}
04 — Where the speed comes from

A 320B model has no right
to feel this quick.

Two tricks do almost all the work. The model drafts its own next tokens and checks them in a batch, and it refuses to re-read text it has already seen.

Speculative decoding DFlash2 · k=7

A small draft model proposes seven tokens ahead. The big model verifies all seven in one pass and keeps the ones it agrees with. Generating tokens one at a time is bandwidth-bound; verifying seven at once is not. Below is the real per-position acceptance rate from a live request — position 1 is almost always right, and acceptance decays with distance.

draft position →measured 2026-09-05
Mean accepted length, best request6.61 tokens
Draft acceptance, best request80.1 %
Draft acceptance, typical range23 – 80 %
Sustained generation23.1 tok/s

Prefix caching 4.92× measured

An agent sends the same 18,000-token codebase on every turn. Without caching, the model re-reads all of it every time. With caching, the second turn skips straight to the new part. This is the single largest win available to anyone running an agent loop.

cold26.69 s
cached5.42 s
identical 17,874-token prompt, back to back

The page-alignment trap

GLM-5.3's hybrid attention caches in 3584-token pages. If max-num-batched-tokens is not a multiple of that page size, the cache silently never hits and you will never see an error — just a mysteriously slow agent.

MAX_NUM_BATCHED_TOKENS=3584  # or 7168. Never 8192.

Measured today, on the live cluster

0.63 s
Fastest short reply
23.1 tok/s
Sustained generation
4.92×
Prefix cache speedup

Single-stream numbers on an otherwise idle cluster, agent lane, reasoning effort low. Generation rate varies with draft acceptance — a request the drafter predicts well runs considerably faster than one it doesn't.

05 — Heat

The fix was one busy-wait.

One Spark sat at 93.7 °C while barely generating anything. The GPU was not the problem. vLLM's worker process was spinning in a one-second busy-wait loop, burning 20 CPU cores doing nothing while it waited for work.

before93.7 °C
after80.3 °C
idle now56.8 °C

Cut the spin

The worker polls for new work. One second of busy-waiting per poll pins every core at maximum clock.

GLM53_SPINWAIT_MS=16

Let the governor breathe

The performance governor holds all 20 cores at peak frequency forever. Schedutil lets them idle down between tokens.

governor = schedutil

Cap the boost

The last few hundred megahertz cost disproportionate heat and buy no tokens per second.

max freq = 3.3 GHz
Worker process CPU, before198 %
Worker process CPU, after123 %
Throughput cost of the fixnone measurable
06 — How it actually went

Five failures first.

The write-ups make this look linear. It was not.

Out of memory, repeatedly

The reference NVFP4 recipe simply would not fit. Four separate configurations died during weight load before the cause was clear.

A migration that half-worked

An in-place upgrade allocated a one-million-token KV cache, then never brought the health endpoint up. Rolled back.

It runs — and it is unusably slow

33 seconds for a one-line question, sometimes answering with nothing at all. The reasoning-effort default was eating the entire token budget.

The cache that never hit

Prefix caching was enabled and reported no errors, and still every request paid full price. The batch size was not page-aligned.

Two lanes, and a cool machine

Priority scheduling separated the human from the robots. The spinwait fix took 13 °C off the hot Spark for free. This is the setup running now.

What we would tell someone starting today

  • ✓ Measure quantization with KL divergence, not with vibes.
  • ✓ Set reasoning_effort explicitly on every single request.
  • ✓ Page-align the batch size, then prove the cache hits with a repeated prompt.
  • ✓ Give the human a priority lane before you let agents loose on the box.
  • ✓ Check CPU temperature, not just GPU. The hot part may not be the one computing.
07 — Take it with you

Recipes and receipts.

Configuration files, benchmark logs and the longer write-ups. Nothing here is theoretical — it all came off this machine.

The configuration that matters

Six lines that took a week to arrive at.

# GLM-5.3-Flash-EXL3-2x-DGX-Sparks/.env
MODEL=brandonmusic/GLM-5.3-Flash-tr3-4bpw   # EXL3 trellis, KLD 0.0246
MAX_MODEL_LEN=262144
MAX_NUM_BATCHED_TOKENS=3584                  # page-aligned, or no cache hits
GLM53_SPINWAIT_MS=16                          # was 1000. 13 degrees C.
EXTRA_ARGS="--scheduling-policy priority"     # quotes are load-bearing
HEAD_IP=10.100.128.1  WORKER_IP=10.100.128.2    # the 200G fabric