🐣 GLM-5.3-Flash (320B) and Qwen3.8-Flash-Next land on the club-3090 moe-cache engine #1117
Replies: 3 comments 6 replies
|
Great work! I'm happily using DS4 Flash 0731 on llama.cpp + moecache ( a forked i made with a cache re-arm system that is missing from the original work), getting 20t/s with the biggest Q4 quant, it could be here too :) |
|
You may want to check this out for a different a vLLM based 2x3090 slug to incubate: https://huggingface.co/albucino/Qwen3.8-Flash-Next-W4A16-FP8PLE pretty impressive numbers on the tin: Measured performance 262,016-token prompt: 1,275.6 prompt token/s; |
Native vLLM rig report: two RTX 3090 GPUs, EPYC 7K62, Derisked AWQRan Full native report and deployment notes: public gist.
The recipe uses the runtime overlays from DominikBucko/qwen38-flash-next-2x3090, with the newer launcher options. Measurements
Decode used three warmups and five measured runs per prompt, with the standard 1,000-token narrative and 800-token code caps. Operational checks and limits
The uniform-haystack checks establish addressability, not retrieval quality on natural documents. Two reporting limitations are recorded in the notes: sudo authentication prevented DIMM-speed and privileged ACS collection, and automatic capture did not recognize this overlay's CPU-offload configuration. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
We just shipped nine slugs on the
llamacpp-club3090moe-cache engine, now at v1.6:llamacpp-club3090/glm53-flash-{dual,multi4,multi8}-{iq3xxs,iq4xs}-moecache— GLM-5.3-Flash, a 320.76B MoE (archglm5next) from Z.aillamacpp-club3090/qwen38-flash-next-{dual,multi4,multi8}-q4kxl-moecache— Qwen3.8-Flash-Next (archqwen4exp)Both run on two 24 GB consumer cards by keeping the routed experts in host RAM and caching hot experts back onto the GPUs. GGUF quants by @unsloth. The
glm5nextandqwen4exparchitectures are vendored from @danielhanchen's upstream PRs; the expert cache is leloch's work (RFC ggml-org#24528). We maintain neither — what we contribute is measurement.The new slugs
All prefixed
llamacpp-club3090/. Context is 204,800 on every one.glm53-flash-dual-iq3xxs-moecacheglm53-flash-multi4-iq3xxs-moecacheglm53-flash-multi8-iq3xxs-moecacheglm53-flash-dual-iq4xs-moecacheglm53-flash-multi4-iq4xs-moecacheglm53-flash-multi8-iq4xs-moecacheqwen38-flash-next-dual-q4kxl-moecacheqwen38-flash-next-multi4-q4kxl-moecacheqwen38-flash-next-multi8-q4kxl-moecacheAll 🐣 Incubating —
--forcerequired, and hidden fromswitch.sh --list(use--list --all).Only the two
dualslugs have booted here. The 4- and 8-card variants are community-validated bydesign: this rig has exactly two 3090s, permanently, so the first person to boot one is the
validation.
🐣 Why Incubating, and how to read the numbers below
Same reasoning as the DeepSeek-V4-Flash slugs (#909), and it has not changed: these are not GPU-bound. Under expert offload the GPU waits on host memory, so what you get is set by your RAM channels, their speed, and your core count — not by having two 3090s. A decode number from this rig would not predict yours.
We publish this rig's absolute numbers below anyway — a datapoint beats silence — but read them
as what this machine did, never as a forecast for yours. The DeepSeek-V4-Flash slugs shipped
with none at all; we think that was too cautious.
Two results here do travel, because both are same-rig A/Bs: the v1.6 engine gain, and the
micro-batch trade further down. Ratios survive a change of hardware in a way absolutes don't.
The v1.6 engine — +46.9% decode at 44K, +69.7% at 87K
v1.6 carries two commits from @danielhanchen's #27754:
0069971(caches the indexer's pooled keys) and5796547f3(invalidates them when a context shift splits a pool). Measured with and without the two commits — same rig, same weights, 4 boots alternating:Decode falloff from shallow to 87K goes from −48% to −16%. It is a ratio on one machine, so it should survive the trip to yours even though the absolute numbers won't.
0069971alone, generation at depth truncates — 60 tokens where the baseline emitted 128, on the same prompt at temperature 0, reproducible across boots. It is not a crash and not a slowdown: pooled keys go stale while still looking complete, so the sparse attention selects the wrong cells.5796547f3removes it. Never take one without the other.Why this is a decode-at-depth story at all
The effect is invisible at short context. Our own first A/B said "no reproducible benefit" — because our bench measured decode only at shallow context and measured the deep legs as prefill. At ~11 tokens of KV the gain really is +4.5%, which was all we were looking at. We added a decode-at-depth leg to the bench and the +70% appeared. If you are evaluating a cache-shaped change, check that your harness exercises the regime it targets.
The numbers — Qwen3.8-Flash-Next, 2× RTX 3090
Canonical bench (3 warm + 5 measured), on the shipped compose as it boots — moe-cache v1.6,
q8_0KV, 204,800 context, no draft model (this GGUF carries no MTP head) but withngram-mod speculation ON at n=8, which is the shipped default and needs no drafter file:
verify-full10/10, all checks passed, including vision on ground truth.config: the experts stream from host RAM, so your number is set by your memory channels, their
speed, and your core count — the same reason the DeepSeek-V4-Flash slugs (#909) shipped with no
throughput figures at all. We publish these because a 36 tok/s datapoint is more useful than
silence, not because they will transfer. A rig with half the memory bandwidth will not see 36.
The numbers — GLM-5.3-Flash, 2× RTX 3090
Canonical bench (3 warm + 5 measured) on the shipped
dualcompose as it boots — moe-cache v1.6,IQ3_XXS, fp16 KV, 204,800 context, DFlash2 drafter on GPU1 at depth 3, thinking on
(
REASONING_EFFORT=max, GLM's vendor default):reasoning_content, so theuser-visible answer lands later than the raw tok/s implies. The same caveat as Qwen applies twice
over here: this is a CPU-offload config and a 320B model — your memory bandwidth sets your number.
verify-full9/10, not a clean sweep. The failure is check 7 (thinking/reasoning): the modelreasoned
"Simple."— 7 characters — against a harness minimum. It failed identically on both armsof the ubatch A/B below, so it is not a regression, but whether it is GLM being terse or a threshold
mis-set for this model is untriaged. Vision passed 4/4 on ground truth.
⭐ The second number that travels: halving the micro-batch buys ~24% decode
Same rig, same image, same compose, only
-ub/-bdiffering — so like the v1.6 result above, theratio should survive the trip to your hardware even though the absolutes will not:
-ub 4096-ub 2048Decode ranges do not overlap on either leg. The mechanism is specific to
glm5next: its kpoolsparse-indexer masks are ~44-45% of the compute buffer and scale with
n_ubatch, so halving ithands that VRAM back to the expert cache. It does not carry to Qwen3.8-Flash-Next —
qwen4exphas no kpool, and we have not measured it there, so those composes are untouched at 4096.
Break-even is prompt ≈ 25× response tokens: below that, 2048 wins; above it, 4096 does. A
forced-thinking model emits long responses, so ordinary interactive turns sit well inside the 2048
region — which is why the
dualcomposes now default to it.multi4/multi8keep 4096, wherelong-context prefill dominates. For bulk long-document prefill on dual, set
UBATCH=4096in yourenvironment before launching.
Worth knowing before you wire GLM into anything, because it surprised us: no per-request thinking
switch works on this build. We tried four request shapes —
reasoning_effortin the body,chat_template_kwargs.enable_thinking,/nothinkin the prompt, and the OpenAI-stylereasoning: {effort}object — and all four were inert. Thinking is controlled server-side only,by the
REASONING_EFFORTenvironment variable on the compose, which defaults tomax(the vendordefault).
So: to run GLM with thinking effectively off, relaunch with
REASONING_EFFORT=low— you cannot doit from the client. Every throughput figure above is thinking-inclusive as a result, and an agent
loop that assumes it can disable reasoning for a cheap turn will not get one.
What you actually need to run these
Host RAM is the hard gate. The experts live in host memory, so this is not negotiable:
Below the RAM figure the box thrashes or OOMs; preflight refuses to launch and prints the number.
The companions are the DFlash2 drafter (1.9 GB, GLM only) and the vision projector (~1 GB). Host RAM
is set by the model, not the topology — the
multi4/multi8variants need the same amount.CPU: core count is a first-class variable here, not a footnote. These composes default
-ttonproc/2, which is portable but is a floor, not the optimum — on our 32-core host
-t 28measured ~20% faster than nproc/2=16. The useful zone is an absolute ~24-32 threads, not a
fraction of your core count, so it is worth setting explicitly for your box:
The useful zone we measured is an absolute ~24-32 threads, not a fraction of your core count.
The reference rig — so you can calibrate the numbers above against your own box:
8-channel server platform feeds CPU-resident experts far faster than a 2-channel desktop, at the
same clock. If you are on a mainstream desktop board, expect materially lower decode than the tables
above — that is the platform, not the config, and it is why we keep saying the ratios travel and
the absolutes don't.
What the two models give you
GLM-5.3-Flash ships in two quant tiers — IQ3_XXS (the reach tier, 33 GB less host RAM) and IQ4_XS. Both carry vision (
glm5nextCLIP projector) and both ship the external DFlash2 drafter pinned to GPU1 at depth 3.Qwen3.8-Flash-Next carries vision, and runs
q8_0KV rather than fp16 — which measured−47% KV footprint and converts directly into expert-cache slots.
It ships n-gram speculation on by default (
ngram-mod, n=8) — that needs no drafter file,being a runtime spec-type rather than a
-mdpath. On this model it measured +64% on repeatedcontext and −1.3% (noise) on first exposure, for ~34 MiB. The gain is cache-residency dependent,
so it pays on multi-turn work over one file and costs nothing measurable on cold traffic. ⛔ Don't
raise the depth: ngram-mod's own default (n_max=64) measured −7.6% here, because a wide verify
batch unions the expert set and every non-resident expert becomes a CPU-side FFN.
What it does not have is a draft model, and the reason is worth stating precisely because
it is an engine gap, not a weights gap:
nextn_predict_layersabsent).Qwen3.8-Flash-Next-MTP-GGUFpublishes a standaloneqwen4expdrafter (blk.48.nextn.*,nextn_predict_layers = 1) and a re-shard of the very UD-Q4_K_XL quant we run, with the head added.qwen4exphas noLLM_GRAPH_TYPE_DECODER_MTPimplementation — 15 other architectures in this build do, includingglm5next, which only gained one upstream on 2026-08-30. Until then the head would load as unused tensors.qwen4exp. When it lands, this slug gets a speculative path.So Qwen Flash runs drafter-free today, and that is a re-test trigger with a PR number attached, not a permanent property.
⭐ And more has landed since — though not in this image. #27977 — "reduce the generation slowdown as context grows", the
qwen4expanalogue of the very change that bought GLM +69.7% at 87K depth in this release — was closed on 2026-09-01, not rejected: its author split it into one PR per change. Three of that series are now merged upstream — #28011 (kv-cells: stop the sequence scan once all sequences are seen, merged 2026-08-30), #28023 (sum the indexer heads by slices) and #28123 (recurrent state rollback), both merged 2026-09-01.b10675, carrying only the two cherry-picked #27754 commits — and two of the three merged after that build in any case. So Qwen Flash's 36.8 tok/s stands exactly as measured, and the upside is a re-test trigger with merged PR numbers behind it rather than an open one, pending an engine rebase.What is NOT tested
Stated plainly, because 🐣 means what it says:
verify-fullwas run on both models (Qwen 10/10; GLM 9/10 — see above), along withtest-moe-cache(44 cases, identical across both prefetch states), a retrieval-correctness gate at 8K/32K/64K, and each dual slug booted on the published image showing expert offload, non-zero cache hits and correct terminating output.multi4/multi8are community-validated by design. This rig has exactly two 3090s. The first person to boot one is the validation.SPEC_N=0, that is a result we would like to see.Getting it
setup.shpulls the weights and the required drafter; the vision projector is opt-in.GLM-5.3-Flash — reach tier (IQ3_XXS, ~114 GB host RAM)
setup.sh glm-5.3-flashdownloads the larger tier and the
iq3xxsslug then finds no weights.GLM-5.3-Flash — default tier (IQ4_XS, ~147 GB host RAM)
Qwen3.8-Flash-Next (~110 GB host RAM)
qwen4expWITH_VISION=1WITH_VISION=1WITH_VISION=1does not break the boot — the compose detects the missing projector,prints the fix, and serves text-only. A silent capability loss, not a crash.
Run it
GLM-5.3-Flash
Qwen3.8-Flash-Next
bash scripts/switch.sh --force llamacpp-club3090/qwen38-flash-next-dual-q4kxl-moecache # ~37 tok/s · :8122Useful env, both models:
THREADS=<n>(default is nproc/2 — portable, but a floor; the usefulzone is an absolute ~24-32) ·
SPEC_N=0(speculation off) ·UBATCH=4096(GLM dual: tradedecode back for prefill on long documents).
GLM only:
REASONING_EFFORT=low— the only way to reduce thinking, since no per-requestswitch works. Qwen only:
THINKING=1— selects the thinking sampler row and--reasoning on.Run the evals yourself
Two non-overlapping passes: behavioural quality (the 8-pack) and operational health. Both models
here are llama.cpp on the moe-cache engine, so there is no engine branching.
One-time setup — three of the eight packs run in Docker sandboxes that build once:
pip install git+https://github.com/noonghunna/benchlocal-cli.git git clone https://github.com/noonghunna/benchlocal-cli bash benchlocal-cli/tools/build-sandboxes.sh # ~30 GB free; prune if tightWithout the images the 5 deterministic packs still run; the 3 sandboxed ones skip with a warning.
benchlocal's sandbox cap
BENCHLOCAL_MODEL_TURN_TIMEOUTis 300 s flat and does not scale withthroughput. One 16,384-token thinking answer takes
16384 / decode_TPSseconds, so anythingslower than ~55 tok/s busts the default. Both models here are well under that:
1200900Leave it at 300 and
cli-40,hermesagent-20andbugfind-15fail as timeouts that read likewrong answers. This is the single most likely way to get a bogus quality result on these slugs.
Quality — GLM-5.3-Flash
its own boot with
REASONING_EFFORT, and the shipped default ismax.Quality — Qwen3.8-Flash-Next
Instruct is the shipped default, so leg A is the bare launch.
THINKING=1selects both thethinking sampler row and
--reasoning on, so unlike the vLLM composes you do not hand-set thesampler.
going back to instruct after a thinking run needs a reboot too — skip it and the "instruct" leg is
silently a second thinking leg, both arms score alike, and the A/B reads as a clean null. benchlocal
catches this: per-pack
thinking_validityin the saved JSON.Why each flag
Each of these exists because its absence produced a wrong number for us:
--sampling-from-servertemperature=0. Without it you measure greedy decoding, not the shipped config.--max-tokens 4096token_limitfailures that look like wrong answers.--thinking-max-tokens 16384--timeout-per-caseBENCHLOCAL_MODEL_TURN_TIMEOUT--repeat 3--sampling-from-serverboth legs are sampled, so single draws aren't quotable.timeoutandtoken_limitare harnessartifacts; only
verifier_fail/wrong_answerare the model. benchlocal retries model verdicts 3×by default but does not retry timeouts, so a
timeoutrow is a single sample against a clock.Operational health
bash scripts/report.sh --full # verify + stress + soak + bench + agentic, redactedDon't pair that with
rebench-full.sh— they re-run the same gates.the suite is tighter here than on a GPU-resident model.
What would help most
Numbers from a rig that isn't this one. Host RAM channels and core count are the variables we cannot cover, and the
multi4/multi8variants have never been booted by anyone. If you run one, thenumbers-from-your-rigissue template is the place.Credits: GLM-5.3-Flash by Z.ai; Qwen3.8-Flash-Next by the Qwen team; GGUF quants and the DFlash2 drafter by @unsloth; the
glm5next/qwen4exparchitectures and both v1.6 commits by @danielhanchen (ggml-org/llama.cpp#27754); the MoE expert cache by leloch (RFC ggml-org#24528); DFlash2 runtime upstream by Xuan-Son Nguyen (#27342).All reactions