Skip to content

ggml adapter: SM120/Qwen3.6-35B target — binding-driven LLM decode windows, MoE catalog family, packless artifacts - #186

Open
LiangSu8899 wants to merge 10 commits into
feat/structures-ggml-adapterfrom
feat/ggml-sm120-qwen36
Open

ggml adapter: SM120/Qwen3.6-35B target — binding-driven LLM decode windows, MoE catalog family, packless artifacts#186
LiangSu8899 wants to merge 10 commits into
feat/structures-ggml-adapterfrom
feat/ggml-sm120-qwen36

Conversation

@LiangSu8899

Copy link
Copy Markdown
Member

Second (arch, model-family) target for the native ggml adapter, stacked on #185: an LLM decode window set for Qwen3.6-35B-A3B (hybrid GDN + attention, 256-expert MoE, MTP speculative decode) on RTX 5090 (SM120), plus the catalog and tooling that make the next same-family model a data change instead of a code change.

What's in here

Windows (fr_win_qwen36_sm120.cu) — fused-region NVFP4 W4A4 GEMV packs (GDN in_proj, attention qkv), the GDN cell span with per-token state snapshots and checkpoint replay for speculative verify batches (M ≤ 4), a format-native MoE expert span that consumes GGUF K-quant blocks in place through ggml's own vec_dot device functions (bit-exact q8_1 activation clone, shared expert folded), out-proj / router / lm-head / spec-draft-head windows. All launches join the host's programmatic-dependent-launch chain.

Zero-configuration defaults — compiled-in windows run by default; GGML_CUDA_FLASHRT_DISABLE=1 reproduces stock, GGML_FLASHRT_NO_<X>=1 disables one window, historic FRT_<X>_SWAP switches remain as A/B overrides. Weights repack in-process on first sight of the tensors (pre-capture hook), byte-identical to the offline packer, so a stock GGUF runs as-is with no side files.

Binding-driven windows — every model-specific constant (pack member tables, region shapes, layer counts, cell dims, head facts) lives in the binding's host_params and reaches the code through a generated constants header (tools/gen_binding_header.py). The window logic is family-level; a same-family model is a new binding plus a header regeneration.

Catalog — new moe_expert_ffn family (routed expert GLU-FFN with exact in-boundary top-k, sigmoid-gated shared expert, format-native consumption, token batches as part of the boundary, executable reference); gated_delta_core v2 adds the snapshot_per_token / replay_in_region state semantics speculative rollback requires; autoregressive_decode_pipeline v3 adds the optional spec_draft stage and speculative conformance. A catalog charter (catalog/README.md) fixes the layer's role: structures express boundaries and never adjudicate — no performance claims or case histories in catalog entries. The pi0.5 binding's pins stay green against all of this.

csrc — the warp-split-K GEMV family gains a next-generation entry (fp4_w4a4_mma_warpsplit_mrows_f32out_sm120): compile-time row-count specialization (a runtime M in the MMA hot loop costs measurable time even at M = 1), f32 output, optional PDL join; an M-rows f32→NVFP4 activation quantizer ships alongside with its device body exposed for fused producers. Existing entries untouched.

Qualification — one-command runner (run_qualification_qwen36_sm120.py): binding manifest, structure pins, binding-header freshness, duplicated-token bit-exact selftest, online-repack byte-identity, pinned perplexity and throughput gates. Six greens on the recorded baseline.

Artifact toolingtools/splice_nvfp4_head.py builds a packless speed-tier GGUF by splicing an NVFP4 lm-head (quantized from the BF16 checkpoint) into the shipping body; the stock nvfp4 kernels then serve the head at swap-tier speed with better perplexity than the side-band pack it replaces.

Receipts (RTX 5090, 24-chunk -ub 1 perplexity, tg128 r=5, greedy server medians with text verification)

configuration tg128 ppl
stock 283 6.0055
default tier (zero-env, stock GGUF) 368 6.1106 (bit-stable across all refactors)
spliced-head artifact (zero-env) 378 6.2290
speculative (-md draft + -bs) 433–444 median text-verified

Negative results are recorded in the pins file rather than the catalog, per the charter.

Notes for the Thor line

The window/matcher code, the binding-driven constants flow, the qualification form and the M ≤ 4 / snapshot / checkpoint disciplines are the reusable parts; the MoE and GDN spans are arch-portable CUDA. The SM120 MMA GEMV needs an SM110 counterpart (or the existing csrc GEMMs) and every judgment re-establishes on Thor's own roofline — in particular the launch-overlap capability differs, so the launch-count verdicts do not transfer.

Second (arch, model-family) target for the native ggml adapter: fused-region
NVFP4 W4A4 GEMVs (GDN in_proj, attn qkv, lm head), GDN cell span with M<=4
per-token state snapshots and checkpoint replay, format-native MoE expert
span over ggml K-quant blocks (bit-exact q8_1 activation clone), out-proj /
router / spec-draft-head windows. All launches join the host's PDL chain;
verify batches up to M=4 are first-class (MTP speculative decode).

Host integration is a CMake option (GGML_CUDA_FLASHRT_SM120 +
GGML_CUDA_FLASHRT_PUBLIC_DIR) compiling this translation unit inside the
host's ggml-cuda build, with all call sites ifdef-guarded. Binding and
qualification gates recorded for the migration baseline.
Region wire buffers (packed e2m1 + atom-layout SF + per-tensor alpha) are
now built on first sight of the weight tensors in an evaluated graph, from
a pre-capture hook: ggml dequant -> bf16 -> global amax -> ue4m3-ceil block
scales -> e2m1 nibbles, reproducing the offline packer byte-for-byte
(FRT_REPACK_CHECK memcmp gate, 40/40 regions identical; perplexity receipt
unchanged). This removes the side-band region pack dependency.

The lm-head keeps its pack: it is quantized from the BF16 checkpoint, which
both scores and drafts measurably better than a rebuild from the GGUF's
Q6_K copy; the online head build remains as a fallback.
- new family moe_expert_ffn v1: routed expert GLU-FFN with exact in-boundary
  top-k routing, optional sigmoid-gated shared expert, format-native weight
  consumption (host K-quant blocks in place, bit-exact activation-quant
  clone) and first-class token batches; reference implementation replicates
  the Qwen3.x softmax/top-k/clamp/renorm convention including tie-break.
- gated_delta_core v2: snapshot_per_token state-update and replay_in_region
  checkpoint variants — the rollback discipline speculative verify batches
  require of stateful regions, with the failure modes documented.
- autoregressive_decode_pipeline v3: optional spec_draft stage plus the
  speculative conformance set (output distribution matches target, explicit
  draft-state rollback, throughput judged on text).
- rewrite the sm120 binding/pins against these families (previous ones were
  placeholders); qkv_pack/linear_proj variant additions are recorded as
  proposals instead of version bumps so the pi0.5 binding's pins stay green.

Registry loads all 18 families; the existing pi0.5 pins verify green
against the updated catalog.
Add the catalog charter (catalog/README.md): a structure entry is a local
boundary expression — dimensions, contracts, variant semantics, executable
reference — serving context alignment against native pipelines and the
torch-side distribution boundary. It adjudicates nothing: performance
numbers, verdicts and case histories are conditional on model/hardware/
host/driver and expire silently, so the only arbiter is a test run against
the live system; dated results live in campaign records and per-binding
qualification gates that are re-established by re-running them.

Scrub the recent entries accordingly: drop campaign evidence and
throughput numbers from moe_expert_ffn and gated_delta_core, reduce
variant comments to pure semantics, drop the judgment-phrased speculative
conformance line from autoregressive_decode_pipeline, keep only the
parity-vs-reference gate on the new family.
…oldered)

The binding yaml becomes the single source for every model-specific
constant in the window translation unit: qkv_pack member tables (names,
rows, offsets, leaders), region shapes and layer counts, gated-delta cell
dims (conv row, state size), out-proj/head names and dims, layer scan
bounds. tools/gen_binding_header.py generates a checked-in constants
header from the binding's host_params section; the window logic itself is
now family-level — a same-family model is a new binding file plus a header
regeneration, with no window-code edit.

Framework-wide ggml naming conventions (ffn_gate_exps, ffn_moe_out, ...)
stay in the window code deliberately: they are host facts shared by every
model on this host, not model facts.

Also brings the binding up to the strict loader contract (token_select
stage, complete_hot_path coverage with stock-served segments declared as
host stages); it now validates through flash_rt.structures.binding with
pipeline coverage required.

Receipts: online repack byte-identity 40/40 vs the offline packs;
tg128 and 24-chunk perplexity unchanged; speculative smoke coherent.
Move the sm120 heavy math out of the ggml window file into csrc as the
next generation of the warp-split-K family (additive; the earlier
bf16out/runtime-M entry is unchanged): compile-time row-count
specialization (a runtime M in the MMA hot loop costs measurable time
even at M=1), f32 output, and an optional programmatic-dependent-launch
join so hosts that overlap every launch keep their chain. The M-rows
activation quantizer ships alongside with its device body exposed for
fused producers.

The ggml adapter now only translates: it includes the csrc device header
for its fused GDN producers and calls the csrc entries for standalone
quantize/GEMV launches. Receipts unchanged: repack byte-identity 40/40,
duplicated-token selftest bit-exact, tg128 and 24-chunk perplexity flat.
Compiled-in windows now run by default: GGML_CUDA_FLASHRT_DISABLE=1 turns
the whole layer off, GGML_FLASHRT_NO_<X>=1 disables one window, and the
historic FRT_<X>_SWAP switches remain as explicit A/B overrides. The
in-process repack and the spec-draft head serving are part of the default
set (the draft head builds lazily, only once a loaded draft model's head
copy is actually seen, so plain runs spend nothing on it); the full-tier
FP4 lm-head keeps its measured quality increment and stays opt-in, as do
the archive windows.

The draft model's own qkv projections match the kind-1 pack shapes and
would be silently swept in; that is a separate acceptance-only judgment,
gated off by default (FRT_DRAFT_REGIONS=1), measured flat here.

Receipts: same-binary env vs zero-env tg128 identical; zero-env
speculative server median matches the env-driven safe tier; zero-env
24-chunk perplexity bit-identical; whole-layer disable reproduces stock.
Offline gates: binding manifest validation, structure-version pins, and
binding-header freshness (the generated constants header must match the
binding yaml). On-device gates re-establish their numbers by running:
duplicated-token bit-exact selftest, online-repack byte-identity against
an offline reference pack, 24-chunk perplexity (pinned bit value), and
tg128 against the tier's pinned baseline with a tolerance band.

First full run: six greens (selftest PASS, repack 40/40 byte-identical,
ppl 6.1106 exact, tg128 within band on the full tier).
Add the FlashRT-edition GGUF flow: an NVFP4 lm-head quantized from the
BF16 checkpoint is spliced into the shipping quantized body
(tools/splice_nvfp4_head.py). The stock nvfp4 kernels then serve the head
at pack-tier speed by themselves, the adapter's spec-draft head serving
wires up from the same tensor by pure shuffle (scale passthrough,
alpha = 1), and the last side-band pack file is gone: the artifact judges
faster-tier speed with better perplexity than the pack-served full tier
on the same body.

Judged along the way, gates recorded in the pins file: serving the NVFP4
head through the fp4-activation GEMV adds no speed over stock's
q8_1-activation mmvq and costs measurable perplexity (archive switch,
opt-in); a whole-model standard requantization loses to the shipping
body both at the floor and in FP4-region cost (region quality follows
the source tensor's quantization); the draft model's shape-colliding
projections stay gated.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant