MQ4-Lloyd (qt=52): per-tensor Lloyd codebook in the MQ4V2 container, -15% KLD at 4 bpw; mq4-pro prefill fix; AWQ rmsnorm rewrite - #768
Open
Kaden-Schutt wants to merge 131 commits into
Open
Kaden-Schutt wants to merge 131 commits into
Kaden-Schutt wants to merge 131 commits into
Conversation
…id-mul producers gated_norm_f32_batched and sigmoid_mul_f32 rewrite a stable batched scratch (dn_normed_batch / fa_attn_out_batch) every layer without dropping the pointer-keyed ensure_fp16_x cache. The Q8 residual WMMA consumer (gemm_q8_0_residual_wmma_gfx12, i.e. the mq4-pro tier's out_proj) then reuses layer L's converted activations at layer L+1. The F16 MQ4V2 GEMM launchers happened to evict the single-slot cache between layers; with all three gfx1201 FP8 prefill paths default-on (#757) nothing evicts it, so mq4-pro batched prefill went incoherent: WT2 KLD 6.42 -> 0.019 (1 chunk), 24-chunk 0.0335 after the fix. Any single FP8 flag off masked it. Producers now call invalidate_x_caches_for(out), matching the gemv.rs producer contract.
…book in the MQ4V2 container
Quantizer: --format mq4v2-lloyd emits qt=52 tensors (byte-identical 136 B
MQ4V2 groups) plus F32[16] <tensor>.lloyd_levels sidecars: a per-tensor
16-level Lloyd-Max codebook, constrained to centered levels {7.5+e : e
finite E4M3} so the FP8 prefill path and the f16 decode path share one
codebook exactly. AWQ sidecars compose as for qt=44.
Runtime: loader rewrites group zero-points (zp' = f16(zp + 7.5*sc)) so
both paths decode w = sc*C[q] + zp'; lloyd_lut.rs derives the E4M3 [u32;4]
and f16 [u32;8] LUTs. Kernels: LUT twins of the FP8 WMMA prefill family
(-DHIPFIRE_FP8_LUT_ARG), of the MQ4V2 GEMV/residual decode kernels and of
the fused gate_up/qkv/qkvza decode kernels (-DHIPFIRE_MQ4G256V2_LUT),
selected by the WEIGHT dtype; every route fails closed on a missing LUT.
Dispatch: three Fused*Mq4G256V2Lloyd keys guarded on lloyd_lut_f16, the
SwiGLU-residual variant admits qt=52 through the LUT residual kernel.
Fixes found on the way:
- FP8-LUT residual wrapper: odd-tail padding copied an uninitialized temp
over Y (dropped the residual stream on every odd-sized prefill chunk).
- Lloyd qkvza FP8: per-slab codebook select keyed on the wave-uniform slab
start row (SGPR) instead of the lane row; re-admits the S2BT8 geometry
(launcher requires all four m % 16 == 0, fails closed otherwise).
- fused_rmsnorm_mq_rotate_awq is now derived from fused_rmsnorm_mq_rotate
(-DHIPFIRE_RMSNORM_AWQ): same prefetch/reduction tree, 13.3 us vs the
retired LDS-staged fork's 18.6 us at K=5120 on gfx1201 (+2.5% decode on
every AWQ'd MQ4V2 artifact). Removes the gfx1100-only _direct variant
and HIPFIRE_GFX1100_AWQ_NORM_DIRECT.
WT2 KLD (24 chunks, gfx1201, prefill scoring, q8 KV): xt 0.0482 -> 0.0408,
base 0.0405 -> 0.0346, pro 0.0335 -> 0.0284 vs the AWQ'd uniform tiers.
Decode gfx1201 xt: 36.2 vs 36.5 tok/s uniform; prefill pp512 1374 vs 1412.
Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…ne, docs, CHANGELOG Kernel: gate_up and qkv FP8-LUT symbols now select the per-tensor codebook once per 16-row slab keyed on the wave-uniform slab start row (as qkvza already did), replacing the per-lane candidate evaluation (mq4_pick2/3). Host launchers fail closed unless every projection m is a multiple of 16. pp512 gfx1201 per-kernel vs uniform: gate_up +1.8% (was +3.0%), qkv +2.0% (was +7%), total prefill -1.6% (was -6.4%). 1-chunk WT2 KLD prefill unchanged (L-base 0.020986). CI: crate maps regenerated (quant_mq4v2_lloyd.rs, lloyd_lut.rs), coverage_tests anchors for MQ4G256V2Lloyd and the three Fused*Lloyd keys. Docs: QUANTIZATION.md qt=52 inventory, quant-formats/mq4-v2.md §11 Lloyd variant, CHANGELOG Unreleased, stale references to the retired AWQ rmsnorm fork rewritten. Plan: docs/plans/2026-09-15-lloyd-fp8-prefill-gap.md. Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…on on gfx1151 T0 (gate-first): gemm_mq4g256v2_residual_wmma.hip gains a -DHIPFIRE_MQ4G256V2_LUT arm (LDS-staged 16-entry f16 codebook, decode w = sc*C[q] + zp'), symbol gemm_mq4g256v2_residual_wmma_gfx11_lloyd, launcher gemm_mq4g256v2_residual_wmma_gfx11_lloyd (base tile, fail-closed off gfx11 wave32 WMMA / k%256). Uniform symbol's preprocessed output unchanged. Throwaway differential: examples/tmp_lloyd_gfx11_diff.rs (to be deleted before merge). Gate criteria and the rest of the port: docs/plans/2026-09-15-lloyd-gfx11-port.md. T1: mq4g256v2_scalar_fusion_ok admits gfx1151 (fused Lloyd decode kernels are scalar wave32); gfx1150/1152 refusal tests; stale fused_qkv.rs comment. Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…fx1151 decode admission T0 gate on the XTX: F16-LUT residual twin +61% vs the uniform F16 base tile (N=384), +71% vs the production MMQ route (N=512); criterion was +10%. Correctness passed (rel-L2 2.7e-4 vs LUT GEMV). Kernel arm, const, launcher and throwaway reverted; plan annotated. Lloyd tiers stay gfx12-only for batched prefill (fail-closed elsewhere); gfx1151 fused decode admission (T1) retained. Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
… KLD, rustfmt on changed files
Registry: files qwen3.8-27b.mq4l{-xt,,-pro}, tags qwen3.8:27b-mq4l{-xt,,-pro},
WT2 KLD in descs, MQ4 DFlash sidecar pairing, mq4-xt re-issued as the AWQ'd
artifact (KLD 0.048, 14.99 GB). Docs/CHANGELOG follow the naming. rustfmt
applied to every .rs changed vs master (CI's changed-file gate).
Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…l arms Raises hipfire-arch-qwen35 bypass 121 -> 128 and bypass_total ceiling 241 -> 248. Traded: the seven gemm_*_fp8_lloyd calls in prefill.rs land as raw launches now so the Lloyd tiers ship on gfx1201; the registry keys with LUT plumbing that retire them come with the gfx11 MMQ-LUT route (docs/plans/2026-09-15-lloyd-gfx11-mmq-lut.md), which needs the same keys. Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
… MMQ/iu4 LUT prerequisite) lloyd_lut_c16_from_levels: code = round_ties_even(16*(L-7.5)), |code|<=120, LE-packed signed bytes in [u32;4]; exact for every E4M3-on-grid level with |e|>=1 (unit-tested), ties-to-even for near-center levels. Field carried on WeightTensor/WeightRef next to the E4M3 and f16 LUTs and filled at the existing sidecar sites. No dispatch/kernel consumer yet; the gfx11 iu4-split twin (docs/plans/2026-09-15-lloyd-gfx11-iu4-split.md) is the consumer. Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…ile temp fold Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…vert arm, annotate plan Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…m kept for A/B) Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…EMV/pad/direct N policy, prefill routing (U4) Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…ents) Rows r and r+8 shared a bank at stride 44 (44r mod 32 = 12r); stride 42 (10r mod 32) visits all 16 even start banks once, keeps b64 alignment, and shrinks LDS 31744 -> 30720 B. Halo (gfx1151), mq4-xt pp512: full_set_occ3 1722 -> 1688 us, full_add_occ3 1684 -> 1643 us, prefill 876 -> 861 ms; eval output byte-identical (md5 cc7f5a26...); 190 VGPR, 0 spills. The A1 software-pipeline variant was screened in the same lane and rejected (+40%, 256 VGPR + 40 spills) and is removed with the HIPFIRE_IU4_VARIANT hook; note the previous 'loader(qwen35)' commit accidentally carried that hook code. Plan: docs/plans/2026-09-15-halo-prefill-plan.md §5-6. Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…nd HIPFIRE_FA2_GFX11_VARIANT (gate pending) Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…ECAR), shared block_i4_128 quant recipe (gate pending) Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…itted IU4 sidecars B1 (attention_q8_0_fa2_gqa.gfx11): fa2_swiz = 2*bit_reverse4(c) with four aligned int32x2 LDS loads per K/V fragment. 7-shape oracle (Q8-K and fwht3-K, b1..b512, L1..L32768) bitwise-equal vs the incumbent. Halo mq4-xt pp8192 per-call 7269/7293/7407 -> 6902/7004/7046 us (-4..-5%). Removing the two compiler memory clobbers (B2) was screened and rejected (gave back half of B1); they stay. C2: RMSNorm/FWHT and SwiGLU/FWHT batched producers emit the IU4 block_i4_128 representation (shared kernels/src/block_i4_128_quant.hip recipe, identical arithmetic to quantize_int4_mmq_ds128) through a type-state prepared handle on gfx1151+IU4 for the 128 attention/FFN inputs and 64 down inputs per chunk; the standalone quantizer stays for the 64 wo/output residual inputs and every non-admitted shape. quantize_int4 launches 256 -> 64 per 512-token chunk; eval output byte-identical (md5 cc7f5a26...); Halo pp512 profile 860 -> 837 ms. Plan: docs/plans/2026-09-15-halo-prefill-plan.md §7-§9. Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…ghtTensor literals, bank +14 dispatch-bypass for the gfx11 MMQ-LUT arms, drop the tmp_lloyd_mmq_diff throwaway, regenerate crate maps bypass: hipfire-arch-qwen35 128 -> 142 (+14 net: the seven gemm_*_mmq_lloyd prefill arms mirror the FP8-LUT arms' registry-key debt; retired together when the LUT keys land), ceiling 248 -> 262. rustfmt on changed files. Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…bypass ceiling raise RATCHET-RAISE: bypass_total 241 -> 262, traded for shipping the MQ4-Lloyd (qt=52) prefill arms as raw launches (7 gfx12 FP8-LUT + 7 gfx11 MMQ-LUT gemm_*_lloyd calls in prefill.rs) ahead of the registry keys with LUT plumbing that retire them Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…f, exact gfx1151) builds group-major duplicates of every IU4-consumed projection at load (~15 GB on 27B); bit-exact; pp2048 IU4 -5% in profile; decode unchanged 14.66" This reverts commit ed33d20.
…r full-tile use (load-path independent)" This reverts commit c57b3b6.
…eight_layout_gm (default off, exact gfx1151), gate/up/down only" This reverts commit a3b3528.
…fx12 fp8-resident is the honest form Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…sured 2-3% slower on prefill; verdicts recorded Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…wn +16%) — IU4 GEMM is weight-byte-latency-bound, not fill-bound; twin removed Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
… uapi, ERT golden tests); kernel.npu_spillover (default off); registry ModelEntry.xdna + manifest v1 stored-zip parser; load_params projection into LoadCtx.xdna Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
…TOPS (writeback-bound), research artifact only; f32-fold slice C spec on file, undispatched Signed-off-by: Kaden Schutt <151092359+Kaden-Schutt@users.noreply.github.com>
… producer fusions (gated_norm, attention reduce)
Both units bit-exact with receipts; measured on the canonical AWQ'd trunk
qwen3.8-27b.mq4-xt (sha256 80e7c624…, size 14987185152), graphs ON.
1. gemv_mq4g256v2_residual on gfx1151 was the only MQ4V2 weight-stream kernel
spilling: 96 VGPR / 36 SGPR / 5 VGPR spills / 24 B scratch per lane, on a
kernel that is 29.2% of decode. Reuse the shipped gfx1100 row-serialized
schedule under an exact-gfx1151 macro (HIPFIRE_GFX1151_RESIDUAL_ROW_SERIAL,
entry gemv_mq4g256v2_residual_row_serial_gfx1151, 32-byte ABI unchanged):
81 VGPR / 27 SGPR / 0 spills / 0 scratch, 16 waves/SIMD. gfx1100 .text
md5 unchanged (acdefd61…). Device memcmp 0 mismatches at (5120,5120),
(5120,6144), (5120,17408), (5119,5120) on both GPUs; greedy md5 identical
before/after (gfx1151 790828f9…, gfx1100 98bca5f0…). Kernel 160.96 ->
154.34 us/call, 185.8 -> 193.8 GB/s (99.7% weight bytes). Graphs-ON decode
A/B in the same tree is neutral (14.595 vs 14.594): gfx1151 AR decode sits
at 90.8% of the box's measured 240.9 GB/s DRAM ceiling, so per-kernel
efficiency no longer transfers. The scratch segment was also what made
Redline PM4 prepare refuse the Halo tape ("GFX10/GFX11 PM4 dispatch does
not yet support scratch (private=24)"); this is the prerequisite for it.
2. AWQ artifacts issued 64 standalone rotate_x_mq_awq launches/token purely
because wo.awq_scale.is_none() gated the two shipped producer fusions off.
Add AWQ twins of the DeltaNet gated_norm->MQ-rotate fusion (48 layers) and
the full-attention reduce->sigmoid-gate->MQ-rotate fusion (16 layers, also
removes 16 sigmoid_mul launches). Divide stays after the reduction and
before signs1/FWHT. Zero spills on all 7 AWQ symbols across gfx1100/
gfx1151/gfx1201, occupancy 16, gfx1201 non-AWQ unchanged; on-device
memcmp EXACT on all five oracle rows; greedy md5 6eda7cf0… identical
baseline/candidate and cross-arch. Launch census 64 -> 0 standalone
rotates/token. gfx1100 decode 48.66 -> 49.05 (+0.80%, 3 fresh processes,
gated +0.55%, attention -0.08%, combined +0.80% with non-overlapping
sample ranges). Adds the missing profile timer on the fused attention
reducer (it was invisible in every kernel census).
Fixture note: the 14.66 gfx1151 decode floor was set on the non-AWQ trunk;
the canonical AWQ'd fixture reads 14.63-14.64 with identical code (n=4 per
arm, start temps matched), i.e. AWQ costs ~0.14% decode / ~1% prefill, 94%
of the prefill share in the eight exact f32 divides of the SwiGLU AWQ twin.
The daemon's shadow field is named aql_host_us for both transports, and the harness printed it as `aql=` even under --pm4, so a retained-PM4 result read as an AQL number. Print `pm4_ib=`/`aql_packets=` per the selected backend and the signed delta vs HIP. Report keys and daemon protocol unchanged (product_bench and tests consume them by name).
Kaden-Schutt
force-pushed
the
mq4-lloyd
branch
10 times, most recently
from
September 17, 2026 19:32
6845a29 to
71a5c64
Compare
After the last dispatch of a retained IB, emit wait_compute_idle() then the architecture-matched full acquire: acquire_system() on Legacy (gfx10/gfx11), acquire_system_gfx12() on Gfx12. CS_PARTIAL_FLUSH drains shaders but does not write back GL2 for a non-shader next consumer (SDMA copy). This is ACQUIRE_MEM with the GL2 writeback bits, not a RELEASE_MEM packet. Unconditional: one packet (+8 dwords) per tape. Applies to all three terminal sites: single-IB, per-lane, single-lane phase. Adds Pm4Commands::trailing_release plus a contract unit test (trailing_release_emits_wait_then_system_acquire: 2+8 dwords, header 0xc0065800). Mirrors upstream e836c13/f325143 byte-for-byte. Discriminator note (honest negative): a tmp SDMA probe (H2D poison reset -> retained-tape replay -> D2H readback vs HIP arm, gfx1100) showed 3840/4096 stale rows/iter in the pre-fix shape, but the trailing acquire did not move it: per-block atomics proved all 16 blocks execute with correct IDs while a HIP checker kernel agreed with SDMA that only block 0 stores surface. That is a different, deeper visibility behavior, not the terminal-GL2 gap, so the probe is not a valid regression gate and is removed (tmp file + lab example entry). The fix is correct and preventive; parity below proves no regression. Gates: cargo test -p redline-rocr -p rdna-compute --lib green (251 + 55; dispatch::upload_raw_copy_failure_hip_frees_owner flakes only under full-suite VRAM pressure, passes in isolation). Harness receipts (qwen3.8-27b.mq4-xt, kv q8, ctx 128, skip-prefill): gfx1201 pre: pm4_ib=26841.0us hip=27627.3us exact=True pass=True gfx1201 post: pm4_ib=26942.6us hip=27598.9us exact=True pass=True gfx1201 post: pm4_ib=26908.2us hip=27619.2us exact=True pass=True gfx1201 post: pm4_ib=26811.6us hip=27560.9us exact=True pass=True gfx1100 pre: pm4_ib=20551.3us hip=20537.2us exact=True pass=True gfx1100 post: pm4_ib=20605.2us hip=20456.9us exact=True pass=True gfx1100 post: pm4_ib=20227.3us hip=20477.4us exact=True pass=True gfx1151 pre: pm4_ib=68013.2us hip=67613.4us exact=True pass=True gfx1151 post: pm4_ib=68004.7us hip=67667.6us exact=True pass=True gfx1151 post: pm4_ib=68082.0us hip=67645.0us exact=True pass=True Tape delta +8 dwords; decode deltas within run noise on all GPUs.
Kaden-Schutt
force-pushed
the
mq4-lloyd
branch
from
September 17, 2026 19:36
71a5c64 to
01d3ca7
Compare
Item 2 — Gfx12RmwAcquirePolicy ladder (redline-rocr/src/pm4.rs:56-88, acquire_rmw_gfx12 :345-351; CurrentSequential rung routes through the pre-existing emitter so default tapes are byte-identical, unit test rmw_acquire_ladder_encodings_are_stable :810). Gfx12 vmem arm in rdna-compute/src/replay.rs acquire_inter_node :331-345 behind HIPFIRE_REPLAY_PM4_GFX12_VMEM_ACQUIRE, default OFF (gate :603-614, test gfx12_vmem_acquire_is_explicit_opt_in :6277); arch-aware call sites :4803, :5013/:5033/:5323. Legacy path untouched. Item 3 — upstream lane partition verbatim: redline-dispatch/src/lanes.rs (840 lines, measured_lanes :151) + src/partition.rs (225 lines); QueuePolicy::Auto consults measured_lanes first (aql/queue_policy.rs:46-55). Only default change: gfx1030 lanes 1->4; gfx1100/1151/1201 pinned by unit test (:102-109, gfx1201 stays 2). Item 4 — CU-mask primitives in redline-rocr/src/runtime.rs (create_with_cu_mask :1187+, CU_MASK_REDUCED handling, abi.rs re-exports); 7 unit tests; no default wired. Triage (gfx1201, qwen3.8-27b.mq4-xt, q8, --skip-prefill --decode-context 128, ROCR_VISIBLE_DEVICES=2): the first version of this pull regressed the retained-PM4 tape — the single-queue pre-dispatch arm called acquire_inter_node instead of gfx12_system_acquire AND the `else if acquire` arm was dropped, so ordinary dependent boundaries emitted no acquire at all (30676 -> 25164 dwords, exact=False). Bisect (replay.rs reverted, everything else on) returned exact=True, attributing it to replay.rs, not the ladder/lanes/CU-mask. Fixed here: pre-dispatch arm restores gfx12_system_acquire() by default (replay.rs:5018-5025) with the HipLlvmVmemL1 rung reachable only under the explicit opt-in; the ordinary-dependency arm is restored (:5026-5039). Attribution table (pm4_ib / hip host us, cmd dwords): | build | exact | pass | pm4_ib | hip | dwords | |-----------------------------------------------|-------|------|--------|--------|--------| | 01d3ca7 baseline (items stashed) | True | True | 26895.2| 27641.8| 30676 | | items 2-4, pre-fix default | False | False| 26699.3| 27653.9| 25164 | | items 2-4, pre-fix + VMEM opt-in=1 | False | False| 26694.9| 27657.6| 25164 | | items 3+4 + ladder, replay.rs @ HEAD | True | True | 26793.2| 27674.5| 30676 | | items 2-4, fixed default | True | True | 26852.2| 27763.1| 30676 | | items 2-4, fixed + VMEM opt-in=1 | True | True | 26752.6| 27718.4| 30676 | Phase-plan line absent from the daemon log in every run (single-queue path; report queue_id=2). Baseline HIP hashes (logits d00b3d5061e56007 kv 134628dbefbcc5e8 rec 1ecb80c8174d99db) reproduced exactly post-fix. Opt-in rung acknowledged in daemon log ("[redline] gfx12 PM4 VMEM RMW acquire rung enabled"); opt-in timing -0.37% vs fixed default on pm4_ib. Unit tests serially (--test-threads=1): rdna-compute 252, redline-dispatch 97 (+11 dispatch, +8 identity integration), redline-rocr 55 — all pass.
…erics)
Opt-in HIPFIRE_GFX12_FA2_FP8 / kernel.gfx12_fa2_fp8 (default off; exact
gfx1200/gfx1201 only). Four FP8 SRC consts prepend #define HIPFIRE_FA2_FP8 1;
HIP renames direct/fwht3k/partial/merge entries under the define. Launchers
select _fp8_ symbols when enabled; U0 LDS stays 65536 (// Ua: 32768). No
separate KernelKey — same exact-gfx1201 FA2 predicates.
Receipts (HOME=/home/kaden/.hipfire-homes/ab1 ROCR=1):
- cargo build --release OK; feature_flags lib test OK
- greedy -t0 -n256 graphs ON content_md5 OFF=ON e20d37a5d7fcc4c35be6fc18a8e71bfa ("Paris"/39)
- gfx1100 FA2 .text body e5ed6e67…; gfx1151 cbf1b9d5… (gfx11.hip untouched)
- gfx1201 base/fp8 bodies identical (direct af023e6c… partial 441544af… merge d10261aa…)
…PU selection `_spawn` unconditionally set HIP_VISIBLE_DEVICES=0 in the child even when the parent selected the GPU with ROCR_VISIBLE_DEVICES alone, so the daemon carried both selectors (they remap differently). Default to GPU 0 only when the caller set neither. Found by ChunkPlan while writing the chunk-widening serve gates; affects every serve_harness battery/chain run on a multi-GPU box.
grow_scratch_buffer retained every replaced buffer once any hipGraph had been captured (std::mem::forget). On gfx1100 five growing prompt shapes retained +199.6/+411.1/+754.9/+1459.9/+2906.8 MB = 5.7 GB, OOMing a multi-turn DFlash session on turn 3. Freeing under a live graph is not safe either (measured: every qwen35 turn empty, HipError 700). Fix (design A: invalidate-on-growth; per-pointer attribution is impossible since captured graphs store only baked device pointers, so wholesale by design; no reservation, no admitted ceiling needed): - grow_scratch_buffer always syncs + frees; the forget branch is gone. - Every Gpu scratch caller checks the factored scratch_will_grow predicate before delegating and drops captured execution state via Gpu::invalidate_for_scratch_growth, which reuses the model-swap teardown invalidate_for_layout_growth (AR + verify/replay graphs + retained Redline rearm). Graphs re-capture lazily; one re-capture per growth event, growth monotonic and bounded by largest shape. - Same treatment for the Drop-less GpuTensor growers (gemv_residual_tmp, paro_x, paro_fused) which leaked unconditionally. - Never invalidates mid-capture/record (would clear in-flight blobs). Receipts (gfx1201, ROCR_VISIBLE_DEVICES=0, HOME=ab0): - tmp_scratch_leak_probe pre-fix steps: 39.8/75.5/151.0 MB (full new sizes retained); post-fix: 18.9/37.7/75.5 MB (increments only), stale graph gone, re-capture + replay clean, no HipError 700. - cargo test -p rdna-compute --lib: 256 passed (incl. 3 new scratch_growth_tests: will-grow predicate, invalidation contract, geometry helpers). - serve A/B single prompt (qwen3.8-27b.mq4-xt): without fix finish=stop coherent 39w; with fix finish=stop coherent, decode 36.6. - serve chain 5 turns (fix): 5/5 finish=stop, 0 empty, growing ctx 72->1364, avg_decode 36.1 (1 capture + 1254 replays in trace). Gates remaining at commit time: serve floor A/B on growth-shaped battery, hipx gfx1100 floor + chain.
Replace the two-perm + v_mul mask expand with an affine-hi (q>=8 -> 0x50+(q-8)) single-table perm plus a v_perm blend keyed on the top nibble bit. Bit-exact: exhaustive on-device check of all 65536 x16 x 2 halves (probe2 candidate B). LUT-arg (Lloyd) path untouched (codegen .text md5 identical). Probe gfx1201 (load-fed, 3 runs <1pc spread): expand-only 0.74x, expand+wmma 0.77x. Per-4-chain ISA: -8 v_mul_lo_u32, -12 v_and, -4 add3, -8 bfi, +8 and_or, +8 or, +4 add_nc (106 -> 94 VALU). Metadata unchanged on all 16 uniform symbols (VGPR/SGPR/LDS/ spill identical, e.g. bt12 238/42/0/0). Eager profiler (prefill 8192, GRAPH=0): gate_up 1921.03 -> 1868.38, residual 716.19 -> 706.42, qkvza 885.45 -> 864.19, qkv 829.04 -> 810.01 us/call, identical call counts. Graphs-ON bench: base == new within 0.4pc quiet (fp8 route is eager-only by dispatch design); greedy md5 identical; decode tg64@128 36.5 tok/s both arms. gfx1100/1151 TU compile fails loud at the new #error (was: wmma builtin error).
…unk; FA2 fp8 plan corrected by the CPU screen The discarded non-AWQ upload (14980361216 B, 9f91556f…) was found under three paths today — ~/.hipfire/models/qwen3.8-27b.mq4-xt on the local box (symlink into the August ladder artifact), /srv/hw-gate/models/qwen3.8-27b.mq4-xt (real file, root-owned, NOT fixed here), and previously on hipx — and silently carried a day of gfx1201 numbers. The local symlink now points at the canonical 80e7c624… artifact; the non-AWQ twin is named qwen3.8-27b.noawq-xt on both boxes. check_fixture.sh fails closed on the known lookalike by size (instant) and optionally verifies the sha256. FA2 fp8 plan (docs/plans/2026-09-17-gfx1201-fa2-fp8-legs.md) corrected by the CPU screen on real layer-35 Q/K/V: e4m3 is exact only to |14|, so the K/V planes are NOT lossless (max-abs 0.096 / tail 0.0063); stage a moves from memcmp to tolerance + KLD. Stage c (fp8 P) is killed: 31.5 % of P underflows at x64, 13.6 % at x256, vs a 0.1 % gate. PV stays f16. Expected row a+b: ~1580/1580/1500/1210 from 1464/1435/1327/1044.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
MQ4L tiers (
mq4l-xt/mq4l/mq4l-pro, quant type 52MQ4G256V2Lloyd): the MQ4V2 tiers re-quantized with a per-tensor 16-level Lloyd-Max codebook instead of the uniform 4-bit grid. Byte-compatible MQ4V2 container (136 B groups, AWQ sidecars, identical size) plus a 64 B<tensor>.lloyd_levelssidecar per 4-bit tensor. Levels are constrained to centered E4M3-representable values so the FP8 prefill path and the f16 decode path share one exact codebook; the loader folds the centering into the group zero-points.WT2 KLD, 24 chunks, gfx1201, prefill scoring, Q8 KV (same protocol as the HF model card):
Speed, gfx1201 (R9700), same card interleaved A/B, warm,
HIPFIRE_VERIFY_GRAPH=0: xt uniform 36.49–36.54 tg / 1410–1415 pp512 / 1276–1281 pp8192; mq4l-xt 36.14–36.17 / 1395–1400 / 1264–1267 (−1.0% / −1.2%). Shipped-xt master reference on the same card: 36.55 / 1417 / 1284 (this branch: 36.58 / 1412 / 1280 — no uniform-path change).Runtime coverage: gfx1201 prefill (FP8-WMMA LUT twins) + decode (fused scalar LUT kernels); gfx1100/gfx1151 decode (T1 admission). gfx11 batched prefill fails closed for now — the F16-WMMA-LUT route was gated and abandoned (+61% vs F16 base on the XTX;
docs/plans/2026-09-15-lloyd-gfx11-port.md); the MMQ byte-LUT route is planned (docs/plans/2026-09-15-lloyd-gfx11-mmq-lut.md) as the next PR.Fixes found on the way
079eb152d):gated_norm_f32_batched/sigmoid_mul_f32rewrite a stable batched scratch without invalidating the pointer-keyed F16 x-cache; the Q8out_proj(gemm_q8_0_residual_wmma_gfx12) consumed the previous layer's activations. Masked while the F16 MQ4V2 launchers evicted the single-slot cache; exposed once all three FP8 prefill paths became default (gfx1201: FP8-WMMA MQ4v2 prefill GEMMs (+28% pp512), opt-in; GDN permlanex16 fix #757). 1-chunk WT2 KLD 6.42 → 0.019; 24-chunk 0.0335. Cherry-pickable.fused_rmsnorm_mq_rotate_awqis now derived fromfused_rmsnorm_mq_rotate.hip(-DHIPFIRE_RMSNORM_AWQ) instead of a stale LDS-staged fork: 18.6 → 13.3 µs at K=5120 on gfx1201, +2.5% decode on every AWQ'd MQ4V2 artifact (fresh xt 35.6 → 36.5). Removes the gfx1100-only_directvariant andHIPFIRE_GFX1100_AWQ_NORM_DIRECT.Hugging Face
hipfire-models/qwen3.8-27b:mq4l-xt/mq4l/mq4l-proadded;mq4-xtre-issued with its AWQ sidecars (the prior upload lacked them: KLD 0.057 → 0.048; new sha25680e7c624…, pinned in AGENTS.md §5);mq4andmq4-probyte-identical to the fresh v2 tiers, untouched. Model card updated.Validation
scripts/serve_harness.py batteryonmq4l-xt(serve path,--speculation off): 5/5 stop, runaway/empty/attractor/retrieval_miss 0, decoded text read.mq4lvsmq4: coherent, correct.cargo test --libon rdna-compute / hipfire-dispatch / hipfire-runtime / hipfire-quantize / hipfire-arch-qwen35; crate maps + coverage tests; rustfmt on changed files.Known
HIPFIRE_AR_GRAPH_TRACE=1shows capture+replay on re-run. Harness artifact under investigation; not caused by this branch (seen on shipped-xt/master arms too).