Skip to content

quant: add Bonsai TQ2G128 (qt=40) and BQ1G128 (qt=41) - #597

Open
nwoolmer wants to merge 1 commit into
masterfrom
feat/ternary-bonsai-27b
Open

quant: add Bonsai TQ2G128 (qt=40) and BQ1G128 (qt=41)#597
nwoolmer wants to merge 1 commit into
masterfrom
feat/ternary-bonsai-27b

Conversation

@nwoolmer

@nwoolmer nwoolmer commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

Rebuilt onto current master (80a572c8) as one Saddle/Ratchet-aligned commit.

This PR exclusively owns the Bonsai low-bit wire formats:

  • qt=40 — TQ2G128: ternary Q2_0-compatible, 34 B / 128 weights.
  • qt=41 — BQ1G128: binary Q1_0-compatible, 18 B / 128 weights.

PR #599 is stacked on this branch and does not remove, redefine, or modify qt40/qt41.

What lands

  • Canonical dtype, loader, quantizer, registry, dispatch, GEMV, dequant, xbatch, and batched-prefill wiring for both formats.
  • SP-E requantization corrections: remove half-applied AWQ, fit the encoder scale rather than using max|w|, and refuse out-of-set ternary code 3.
  • check_ternary_pack_health and K%128 geometry guards.
  • Registry tags bonsai:27b-tq2, bonsai:27b-bq1, plus the bonsai alias.
  • Saddle layout and current cleanup-ratchet integration; no legacy qwen35 monolith reintroduced.

Quality evidence

Matched f32-KV KLD against the pinned qwen3.6-27B MQ4 teacher:

artifact SHA-256 KLD
teacher 86a5f80fd29d545abb1093dead242725ced6d68b8607c6d566d897b1a82442dc
TQ2G128 b2ea3f7f2160fe961d5ed256f474a4428b0f88e3a923e70fa80d3bf3bde5098e 0.504695
BQ1G128 83dc56409efa0503e171d91fffcad25c8a9f000120f61cf9cbba589a09fbbb07 0.620867

The result is the fixed uniform codebook, not the raw bit budget: the project’s free-codebook MQ2-Lloyd control remains materially better than uniform MQ2.

Architecture validation

gfx1201

  • Exact CPU/GPU parity passed for dequant, GEMV, tail cases, xbatch, prefill, and WMMA routing.
  • bonsai:27b-tq2: five coherent serve-harness battery turns, empty=0, attractor=0; avg prefill 204.7 tok/s, avg decode 32.3 tok/s.
  • bonsai:27b-bq1: five coherent turns, empty=0, attractor=0; avg prefill 295.8 tok/s, avg decode 41.2 tok/s.
  • Validation daemon md5: 3cec9bea52ff28927377f78b37906a62.

gfx1010

Final-source scripts/compile-kernels.sh gfx1010 compiled the relevant scalar family:

  • dequant_{tq2g128,bq1g128}_to_f16
  • gemv_{tq2g128,bq1g128}
  • gemm_{tq2g128,bq1g128}_prefill
  • gemm_qkvza_tq2g128

The gfx1010 compiler correctly rejects the wave32-WMMA variants. A direct TQ dequant run passed on the available gfx1010 host; a full 27B BQ serve load was blocked by that host’s 8.6 GB VRAM rather than a kernel or dispatch failure.

Gates

  • Runtime/dispatch integration: 944 passed, 3 ignored.
  • Quantizer: 128 passed, 4 ignored.
  • Cleanup ratchets: 21/21, bypass inventory 222, no violations.
  • Generated crate maps: 39/39 match the final tree.
  • Low-bit PM4 direct-HIP shadow comparison remains false on the unchanged canonical MQ4 baseline too, so it is recorded as an oracle mismatch rather than claimed as a pass.

No merge is performed by this update.

@nwoolmer
nwoolmer force-pushed the feat/ternary-bonsai-27b branch 3 times, most recently from 718d418 to e55628b Compare August 18, 2026 09:36
Kaden-Schutt added a commit that referenced this pull request Aug 18, 2026
…t ledger

A ceiling cannot see substitution. `arch_key_dispatch <= 12` stays green if you
delete a justified site and add an unjustified one, and that is the exact shape
of f00fa80, where landing qt=43 deleted six match arms belonging to other
formats while the build stayed green. check-layering.py already knew this: it
emits UNLISTED (in the tree, not in the table) and STALE (in the table, not in
the tree) rather than a number. This applies that shape to two more surfaces.

docs/quant-formats/qt-register.txt — 36 rows, one per QuantType variant, each
carrying a load disposition. Asserted by check-quant-registry.py:

    qt_unlisted  qt_stale  qt_unparseable  qt_disposition_mismatch    all == 0

The first draft of this gate was three counts including `qt_unregistered <= 10`.
That ceiling was uninterpretable: ten variants were a mix of deliberate
non-passthrough (22 is an index tensor, 28/29 load via paro.rs, 31-37 via arch
loaders) and genuine omissions like cf061b7, where qt=40's encoder, GEMV and
is_mq arms all landed and the model would not load. A declared disposition per
row makes those two cases mechanically distinguishable.

The register also adjudicates allocation. PR #597 (BQ1G128) and PR #599
(MQ1G1024GL) both claimed qt=41; ruled for #597, since MQ1G1024GL was never
wired or tested and BQ1G128 is substantially the same format. 40 and 41 are held
as `reserved`, the one disposition exempt from STALE so a number can be claimed
before its variant exists -- a register that can only mirror the present cannot
stop two branches claiming the same number, which is the case it exists for.

docs/governance/debt-dispatch-bypass.txt — 222 arch-crate call sites reach
Gpu::gemv_*/gemm_*/fused_* directly instead of resolving through
hipfire_dispatch::KernelRegistry, which has existed since e822b31 (2026-05-30)
and which one and a half arch crates use. This is a DEBT table, not a purity
check: every row is permitted, growth fails, and paying down is a one-line edit.

    bypass_unlisted  bypass_stale  bypass_regressions  bypass_slack   == 0
    bypass_total                                                      <= 222

bypass_slack is the one that makes it converge rather than stall. Migrating a
crate without lowering its row leaves a stale allowance that the debt can
quietly regrow into; asserting slack at 0 forces the ledger down whenever the
tree improves.

Negative-controlled, not assumed. Substitution -- swap one register row out and
a fake one in, row count unchanged at 36 -- fails with qt_unlisted=1 qt_stale=1.
Substitution across crates -- cohere2moe +1, qwen35 -1, bypass_total unchanged
at 222 -- fails with bypass_regressions=1 bypass_slack=1, where a total-only
ceiling passes. Disposition flip, register/enum name drift, a deleted from_u8
arm, and a reserved row demoted to passthrough each fail on their own metric.
Baseline and restore green every time.

Ratchet goes 12 -> 21 asserted metrics, 0 violations. Workspace 0 errors.
Kaden-Schutt added a commit that referenced this pull request Aug 18, 2026
Every gate this programme built was a script a human had to remember to run.
Nothing in CI invoked leanup-ratchets.sh, check-layering.py,
check-arch-dispatch.py or check-crate-maps.py; grepping for them outside
scripts/ returns only comments in Cargo.toml. no-gpu-ci.sh does run
tools.change_gate.tests.* -- it tests the gate selector without ever using it.

Phase 3A's mandate is that every gate either fails on regression or is deleted.
A gate nothing runs fails on nothing, which is the same defect as the four
self-certifying checks 3A was created to find, arrived at from the other side.

The job is GPU-free and asserts, not advises: these thresholds are green on the
branch introducing them, so a red is a real regression rather than lint debt.
scripts/gates.sh is the separate model/GPU harness and still needs hardware; it
is deliberately not wired here.

ratchet-diff runs PR-only and needs fetch-depth: 0, because it reads the base
revision's thresholds and a shallow clone has no merge base to resolve.

Also refreshes crates/hipfire-quantize/map.md, which ae18341 made stale by two
lines -- caught by running the job locally before wiring it, which is the whole
argument for wiring it.

Consequence worth stating plainly: this will red #597 on landing. It adds qt
40/41 to RAW_CODECS without from_u8 arms or register rows, so qt_unlisted goes
to 2. That is the gate doing its job on a real defect, not collateral damage,
but it lands on someone else's ready PR and they should hear it from a person
rather than from a build failure.
@Kaden-Schutt
Kaden-Schutt force-pushed the feat/ternary-bonsai-27b branch from 02af60e to e1573b9 Compare August 18, 2026 23:32
@Kaden-Schutt Kaden-Schutt changed the title Bonsai-27B (1-bit + ternary) port, SP-E ablation, and registry entries quant: add Bonsai TQ2G128 (qt=40) and BQ1G128 (qt=41) Aug 18, 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