Skip to content

Support pruned expert variants (GSQ-RCO-Coder: 256 of 512 experts) - #54

Merged
Niko1221 merged 8 commits into
Niko1221:mainfrom
pjgmobile:pruned-geometry-support
Sep 28, 2026
Merged

Niko1221 merged 8 commits into
Niko1221:mainfrom
pjgmobile:pruned-geometry-support

Conversation

@pjgmobile

Copy link
Copy Markdown

Support pruned expert variants (GSQ-RCO-Coder: 256 of 512 experts)

Motivation

ISTA-DASLab recently published Qwen3.8-Flash-Next-GSQ-RCO-Coder-GGUF — the same
architecture with half the routed experts pruned away per layer (512 → 256,
qwen4exp.expert_count = 256, still 10 active). The engine currently specialises to the
canonical geometry in a number of places, so a pruned model fails at a different spot for
each one: the pack tool divides by a hardcoded 512, the pack loader validates against the
compile-time default, the runtime graph is default-constructed, the prefill kernels and
buffers assume 512, and serve mode additionally demands a canonical profile-filled cache.

This PR threads the model's own declared expert geometry through those paths so pruned
variants boot and run, while canonical behaviour stays byte-identical.

Changes

  • tools/iq_pack.py — N_EXPERT = 512 was hardcoded; the expert count is now derived
    from the router tensor's shape (ffn_gate_inp.weight, dim 1) with a uniformity check
    across layers. Blob sizes, offsets and the native_experts.txt header all follow it.
  • src/kernels/cpu/expert_layout.cpp — expert_layout_load() trusted the caller's
    geometry (a compile-time default) for the contiguity stride. It now parses
    n_expert from the pack header (v3 headers already record it) and uses that for both
    the stride and the stored layout, so ArenaExpertSource's geometry check passes.
  • include/strata/artifact/gguf_reader.hpp — Qwen4ExpGuard validated every GGUF
    against canonical constants. experts/experts_used now default to 0 = presence-only;
    block count, hidden size and head counts are still hard-validated.
  • src/program/generate.cpp — the runtime ModelGeometry was default-constructed;
    it now reads qwen4exp.expert_count / expert_used_count from the --native shard
    (K too). The MTP drafter deliberately keeps the canonical geometry via a
    static const ModelGeometry — the draft layer is the original 512-expert head, and it
    sizes its own arena from it (speculation works unchanged; acceptance 74-85% measured).
    The serve-mode gate also no longer demands the profile-filled graph-hit path: an
    on-demand (--expert-cache auto) cache is a valid serve configuration.
  • src/core/layer.cpp — the native fused router stays canonical-only; non-canonical
    geometry falls back to the generic router_top10 instead of erroring.
  • src/prefill/* — the NE = 512 constant is replaced by the geometry's expert
    count in buffer sizing, host loops and residency indexing; route_kernel is
    templatized on registers-per-lane (512 → 16, 256 → 8, anything else takes the generic
    router_top10); route() gained an n_expert parameter; moe_set_bytes() likewise.

Design notes

  • The model file is the authority on its own MoE shape; the compile-time defaults remain
    as fallbacks and for the canonical fast paths.
  • The draft/target split is intentional: pruning changes the target's routed experts but
    the shipped MTP draft is still the original head, so it must keep 512x10 sizing.
  • Profiles: the shipped data/expert-profile.bin is 48x512. For a pruned model we
    remapped the ranked (layer, expert) pairs onto the survivor indices using the release's
    published tensor-allocation/*.rco-allocation.txt (Section 2 records each survivor's
    original index) — 8000 → 5492 pairs survived remapping, trimmed to fit VRAM. A
    make_profile.py run against pruned-model routing would do this properly; happy to
    follow up with that as a companion tool.

Testing (Ryzen 5 5600X, RTX 3090 24 GB, CUDA 13.1)

  • Pack built from the IQ1_M pruned release (shard 2 is byte-identical to the canonical
    n-gram table; symlinked, no re-download).
  • Pruned lane boots: 11 pool workers, 262144 ctx, KV int8, remapped profile
    (4500 slots), MTP draft over the canonical head.
  • ~3.5-hour real agentic coding session through llama-swap (three.js scene build):
    peak 192k tokens, one omp compaction, zero engine errors, decode 27-42 tok/s
    (post-0.1.14 AVX2 i-quant kernels: 38.7 cold / 42.6 warm on fixed prompts vs 23.1/24.6
    before this upgrade), draft acceptance 65-85%.
  • Canonical lanes unaffected: Q2_0 daily driver answers at its usual speed (53.6 tok/s
    spot check), IQ2_XS and vision configs untouched.

Disclosure

This PR was authored by GLM-5.3-Flash (ZCode agent); Pete (pjgmobile) tested it on real
workloads overnight and submitted it.

pete added 8 commits September 26, 2026 17:39
…ontext instead of rejecting

Agentic clients legitimately request the model's full output cap with a long
prompt (e.g. prompt 131,888 + max_tokens 130,298 on a 262,144 window: rejected
over a 42-token overshoot). Default behaviour is unchanged: without the flag
the server still rejects with 400, like llama.cpp. With --fit-max-tokens the
server clamps max_tokens to the remaining room (max_context - CTX_SLACK -
prompt, floor 1 token) and answers.

Measured on a 262,144-token host: prompt 251,455 + max_tokens 131,072 ->
HTTP 200, completion_tokens 10,681 (= 262,144 - 251,455 - 8), finish length.
Flag off: byte-identical 400. Small requests unaffected in both modes.
# Conflicts:
#	serve/server.py
- iq_pack.py: derive n_expert from the router tensor shape (was hardcoded 512)
- expert_layout.cpp: parse the pack header's recorded n_expert instead of the
  caller's compile-time canonical geometry; use it for the contiguity stride
- gguf_reader.hpp: Qwen4ExpGuard expert-count checks become presence-only
- generate.cpp: read qwen4exp.expert_count/expert_used_count from the model
  file into the runtime geometry; MTP drafter keeps canonical geometry (the
  draft is the original 512-expert head); serve gate allows profile-less
  caches; K from metadata
- layer.cpp: native fused router stays 512x10-only, generic top-k fallback
- prefill: expert count taken from the geometry everywhere; route_kernel
  templatized (512->16, 256->8 registers/lane, else generic router_top10)
@Niko1221

Copy link
Copy Markdown
Owner

Thank you @pjgmobile - this is exactly what the Coder needs, and it reads cleanly: the model file as the authority on its expert count, the canonical fast paths untouched, and the MTP draft deliberately kept on the 512-expert geometry (the right call - the shipped draft layer is the original head).

I've merged it into the branch for the next release and built on it:

  • Expert profile: data/expert-profile-coder.bin ships with it - the full 48 x 256 ranking: the shipped profile mapped through section 2 of the release's rco-allocation.txt (5,492 of the top 8,000 survive, as you found), then every other kept expert. With 2,537 slots on a 12 GB card, 72% of the expert reads of a 4K code prompt hit the GPU (a wrong index mapping would give about the slot share, ~21%), so the mapping holds. tools/make_profile.py also takes --n-expert now.
  • Setup: START-HERE.bat --setup --family coder. Its shard 2 and vision encoder are byte-identical to the original's, so with the original installed only the 29.6 GB shard 1 is downloaded, and 32 GB of RAM is enough to install it.
  • Measured here (RTX 5070 12 GB, Ryzen 5 7600, 64 GB, the settings setup writes), 1K / 4K / 32K / 64K / 128K / 262K: prompts 599 / 1,152 / 1,298 / 1,350 / 1,266 / 1,034 tok/s, output 53 / 51 / 53 / 51 / 44 / 43 tok/s, answers coherent at every length. Its experts are stored as IQ2_S-IQ4_XS / IQ4_NL / Q2_0 ("IQ1_M" is just the release name), so the MMQ prompt path and the AVX-512/AVX2 row kernels all apply - and with half the experts the whole 23 GB arena pins and a 12 GB card holds twice the share of them.
  • Images work with the original's encoder (it read a Monitor screenshot's numbers correctly). The experimental speed projection loads and runs on it too.
  • The original models are unchanged by the PR (Q2_0 and IQ3_S at 4K and 32K within run-to-run noise); it also builds on Linux.

It goes out with the next release, and the README gets the Coder's row - thanks again for the overnight testing.

Niko1221 added a commit that referenced this pull request Sep 28, 2026
- setup: a third family, "coder" (IQ1_M), with its own expert profile; its
  shard 2 and vision encoder are the original's files and are reused; 32 GB of
  RAM is now enough to install (the Coder's experts are 23 GB).
- data/expert-profile-coder.bin: the shipped ranking mapped onto the kept
  experts through the release's rco-allocation.txt (72% GPU hits, 12 GB card);
  tools/make_profile.py takes --n-expert.
- README/DETAILS: the Coder's speeds (prompts 599-1,350 tok/s, output
  43-53 tok/s, 1K-262K) and what it is; bench/results/2026-09-28-coder.
- The experimental speed projection can be turned on for the Coder too.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0154bwiad8gY7wRehCXy27pN
Niko1221 added a commit that referenced this pull request Sep 28, 2026
…ert count, PR #54)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0154bwiad8gY7wRehCXy27pN
@Niko1221
Niko1221 merged commit b3e5d6f into Niko1221:main Sep 28, 2026
@Niko1221

Copy link
Copy Markdown
Owner

Released in v0.1.16: START-HERE.bat --setup --family coder installs the Coder (with the original installed, only its 29.6 GB shard 1 is downloaded), and the README has its row. Thanks again!

13600k added a commit to 13600k/Strata-for-daniel that referenced this pull request Sep 28, 2026
Brings in engine 0.1.13-0.1.20 and upstream PRs Niko1221#42-Niko1221#44, Niko1221#54, Niko1221#59, Niko1221#62-Niko1221#65,
Niko1221#67, Niko1221#69 on top of the fork's experimental multi-GPU expert caches. Host
test suites pass (expert placement 5935 checks, conversation cache, setup
GPU selection, GPU telemetry, IQ pack, calibration); CUDA build and GPU
parity remain pending hardware validation.
MistVVK pushed a commit to MistVVK/XeStrata that referenced this pull request Oct 3, 2026
MistVVK pushed a commit to MistVVK/XeStrata that referenced this pull request Oct 3, 2026
…ko1221#54)

- setup: a third family, "coder" (IQ1_M), with its own expert profile; its
  shard 2 and vision encoder are the original's files and are reused; 32 GB of
  RAM is now enough to install (the Coder's experts are 23 GB).
- data/expert-profile-coder.bin: the shipped ranking mapped onto the kept
  experts through the release's rco-allocation.txt (72% GPU hits, 12 GB card);
  tools/make_profile.py takes --n-expert.
- README/DETAILS: the Coder's speeds (prompts 599-1,350 tok/s, output
  43-53 tok/s, 1K-262K) and what it is; bench/results/2026-09-28-coder.
- The experimental speed projection can be turned on for the Coder too.
MistVVK pushed a commit to MistVVK/XeStrata that referenced this pull request Oct 3, 2026
Hugua700 pushed a commit to Hugua700/Strata that referenced this pull request Oct 6, 2026
Hugua700 pushed a commit to Hugua700/Strata that referenced this pull request Oct 6, 2026
…ko1221#54)

- setup: a third family, "coder" (IQ1_M), with its own expert profile; its
  shard 2 and vision encoder are the original's files and are reused; 32 GB of
  RAM is now enough to install (the Coder's experts are 23 GB).
- data/expert-profile-coder.bin: the shipped ranking mapped onto the kept
  experts through the release's rco-allocation.txt (72% GPU hits, 12 GB card);
  tools/make_profile.py takes --n-expert.
- README/DETAILS: the Coder's speeds (prompts 599-1,350 tok/s, output
  43-53 tok/s, 1K-262K) and what it is; bench/results/2026-09-28-coder.
- The experimental speed projection can be turned on for the Coder too.
Hugua700 pushed a commit to Hugua700/Strata that referenced this pull request Oct 6, 2026
anon761 pushed a commit to anon761/Strata-upstream that referenced this pull request Oct 6, 2026
anon761 pushed a commit to anon761/Strata-upstream that referenced this pull request Oct 6, 2026
…ko1221#54)

- setup: a third family, "coder" (IQ1_M), with its own expert profile; its
  shard 2 and vision encoder are the original's files and are reused; 32 GB of
  RAM is now enough to install (the Coder's experts are 23 GB).
- data/expert-profile-coder.bin: the shipped ranking mapped onto the kept
  experts through the release's rco-allocation.txt (72% GPU hits, 12 GB card);
  tools/make_profile.py takes --n-expert.
- README/DETAILS: the Coder's speeds (prompts 599-1,350 tok/s, output
  43-53 tok/s, 1K-262K) and what it is; bench/results/2026-09-28-coder.
- The experimental speed projection can be turned on for the Coder too.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0154bwiad8gY7wRehCXy27pN
anon761 pushed a commit to anon761/Strata-upstream that referenced this pull request Oct 6, 2026
…ert count, PR Niko1221#54)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0154bwiad8gY7wRehCXy27pN
jerem91150 added a commit to jerem91150/Strata that referenced this pull request Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants