Laguna: mixed-precision quant support (APEX IQ4_XS/Q6_K, official BF16) + metadata-driven rope - #633
Open
jasontitus wants to merge 4 commits into
Open
Laguna: mixed-precision quant support (APEX IQ4_XS/Q6_K, official BF16) + metadata-driven rope#633jasontitus wants to merge 4 commits into
jasontitus wants to merge 4 commits into
Conversation
Load and run the community APEX exports of Laguna S 2.1
(e.g. Myric/Laguna-S-2.1-APEX-GGUF): q6_k token embedding, attention,
and output head; q8_0 dense/shared experts; routed experts per-layer in
{iq4_xs, q5_k, q6_k}; and the full 1M-token yarn rope config.
- ds4.c: IQ4_XS tensor type (block struct, kvalues_iq4nl codebook, CPU
reference dequant); routed-expert block support; a third "APEX" Laguna
weight layout (marker: q6_k token_embd) beside legacy and signal-q8;
Laguna context_length/rope scale+attn factors adopted from GGUF
metadata after a coherence check (orig_ctx * factor == context_length)
so the conservative 256K (factor 32) and full 1M (factor 128) exports
both load; q6_k attention qkvg decode branch via the generic per-type
matmul.
- metal/moe.metal: kernel_glm_iq4_xs_pair_swiglu_f32,
kernel_glm_iq4_xs_down_f32, and kernel_glm_q6_K_pair_swiglu_f32
(sub-block-per-thread simdgroup QMV, constant-memory codebook LUT,
hoisted per-block scales); dequantize_iq4_xs template hook plus
mul_mm_id instantiations (f32/f16/ff32, and pair_swiglu_f16 for q6_K
and iq4_xs) for the prefill GEMM path.
- metal/get_rows.metal: kernel_get_rows_q6_K_f32 for the q6_k embedding.
- ds4_metal.m: IQ4_XS enum, new pipelines wired into creation/teardown
and the required-pipeline check, gate-pair/down type whitelists, both
QMV dispatch sites (pipeline pick, grid sizing, profile labels),
mul_mm_id per-type switches, get_rows q6_K dispatch, and a Q6_K case
in ds4_gpu_quant_row_bytes (batched embedding sizing).
Measured on an M5 Max 128 GB vs the Q4_K_M export (ctx 8192, greedy,
same corpus): perplexity 13.267 vs 14.027 (-5.4%); decode 50.7 vs
~57 t/s (-11%); prefill 108-119 vs ~190 t/s (-40%, dominated by the
unfused q6_k attention projections -- clear optimization headroom).
The 1M rope export also lifts Laguna's 256K session ceiling, making
--think-max (ctx >= 393216) reachable on this model.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0115FzobY8yCyKaughKNLQ1f
Two follow-ups to the APEX enablement, measured on an M5 Max 128 GB against the same-binary pre-optimization baseline (greedy, interleaved arms): - Route batched q6_K dense matmuls (n_tok >= 32) through the tiled mul_mm GEMM instead of the per-token QMV, which re-read the whole weight matrix once per token. One new kernel_mul_mm_q6_K_f32 instantiation of dense.metal's existing template (moe.metal follows it in the concatenated library, so its block_q6_K/dequantize_q6_K are in scope). APEX attention prefill at 8K tokens now runs within 11% of the Q4_K_M export (376-391 vs 430-434 t/s) where the QMV path had been the dominant prefill cost. - Vectorize the iq4_xs pair-swiglu and down QMV inner loops: four uint32 weight loads per 16-byte slice (was 16 byte loads per pointer) with in-register nibble extraction, float4 activation loads. Decode reaches effective parity with the Q4_K_M export (~51-57 vs 52-54 t/s; pre-optimization 50.6-50.7). Perplexity gate on the fixed corpus: 13.100 post vs 13.267 pre (the small shift comes from the GEMM's f16-staged accumulation, the same numerics class as the existing q8_0/q4_K dense GEMM paths; Q4_K_M reference 14.027). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0115FzobY8yCyKaughKNLQ1f
…oads The dequantize_q6_K/dequantize_iq4_xs template hooks stage every attention (mul_mm) and routed-expert (mul_mm_id) GEMM tile for the APEX export; their scalar byte loads and branchy quarter decode accounted for nearly all of the export's prefill deficit. Rework both hooks with word loads and branchless extraction, keeping the per-element arithmetic byte-for-byte identical. Alignment note: block_q6_K is 210 bytes, so consecutive blocks alternate between 0- and 2-mod-4 addresses — 16-bit loads are the widest always-aligned access for its payload. (An earlier uint version of this hook silently misdecoded the misaligned half of the blocks: teacher- forced perplexity moved only +0.25%, but greedy generation degenerated — caught by the bit-exactness gate, which reproduces ppl=13.100008639 exactly for the shipped form.) block_iq4_xs is 136 bytes (0 mod 4), so its hook keeps 32-bit loads. Also adds Metal-4 MPP direct-RHS instantiations for the q6_K dense GEMM with an aligned-prefix/remainder split in the host dispatch. They are dormant in the Laguna graph path, which deliberately suppresses tensor matmuls for prefill route stability, but engage wherever MPP is permitted. Measured (M5 Max 128 GB, 15K-token prompt, 6 interleaved pairs with cooldowns): APEX prefill 442 t/s vs Q4_K_M 454 t/s — -2.6% +-3.0%, parity within noise, from -12.4% +-1.7% before this change. Decode unchanged (parity), perplexity unchanged (13.100 vs Q4_K_M's 14.027). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0115FzobY8yCyKaughKNLQ1f
Poolside replaced laguna-s-2.1-Q4_K_M.gguf at repo main with a
mixed-precision build (HF fc4e481, "Q4_K_Mx40-BF16x8"): the existing
signal-q8 recipe -- q8_0 embedding/attention/output/dense/shared, q4_k
routed experts on layers 1-39 -- plus bf16 routed experts on layers
40-47. Everything but the bf16 experts already loaded, so this adds
just that type:
- ds4.c: bf16 as a routed-expert type (2 bytes, 1 element per block)
and in the Laguna layout validator's per-layer routed check.
- metal/moe.metal: dequantize_bf16_16 tile-staging hook with
mul_mm_id f32/f16 instantiations for prefill, plus
kernel_glm_bf16_pair_swiglu_f32 / kernel_glm_bf16_down_f32 for
decode. bf16 -> f32 is a 16-bit left shift into the f32 bit
pattern; there are no blocks or scales to unpack.
- ds4_metal.m: type enum, pipelines (creation, required-pipeline
check, teardown), gate/down type whitelists, both QMV dispatch
sites with grid sizing and profile labels, mul_mm_id switches.
Verified on an M5 Max 128 GB: the model loads (89.43 GiB resident,
89.88 GiB planned at ctx 8192, ~10 s residency), generates coherently,
and scores perplexity 13.548 on the same corpus where the plain Q4_K_M
export scores 14.026 and the community APEX i-quality export scores
13.100. Decode 56.9 t/s -- the fastest of the three, since bf16 needs
no unpacking.
Two practical notes for anyone on a 128 GB machine: the file is 89.4
GiB against the previous 63.6 GiB under the same name, so it needs a
mostly idle machine (a first attempt with ~30 GiB held by other
applications thrashed and never became resident), and Laguna has no
--ssd-streaming fallback ("--ssd-streaming is not implemented for
Laguna S 2.1 yet") if it does not fit. At 256K context it would plan
~107 GiB, which leaves very little headroom.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0115FzobY8yCyKaughKNLQ1f
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.
Laguna: mixed-precision quant support (APEX IQ4_XS/Q6_K, official BF16) + metadata-driven rope
Adds support for the mixed-precision Laguna S 2.1 exports that ds4 currently
rejects, closes the resulting prefill gap, and reports two artifact issues
found along the way.
Branch:
laguna-apex-quants(four commits on top oflaguna-s2.1).All numbers measured on an M5 Max 128 GB, Metal backend, on this branch as
submitted, so they should reproduce directly.
What this enables
Myric/Laguna-S-2.1-APEX-GGUFi-quality (68.9 GiB, 5.03 bpw)unsupported Laguna quantization layout marker q6_kQ4_K_Mx40-BF16x8(89.4 GiB)expected context_length=262144 … got 1048576Commits
d3935ba— APEX quant support. New IQ4_XS type end-to-end (block struct,codebook, CPU reference dequant, Metal QMV pair-swiglu/down kernels,
mul_mm_idinstantiations), a Q6_K routed pair-swiglu kernel, Q6_Kattention/embedding/output acceptance, a third Laguna weight layout beside
legacy and signal-q8, and Laguna
context_length/rope scale+attn factorsadopted from GGUF metadata after a coherence check
(
orig_ctx × factor == context_length) instead of pinning one export.0f2d58d— first optimisations. Batched Q6_K dense matmuls routedthrough the tiled GEMM instead of a per-token QMV; vectorised IQ4_XS QMV
inner loops.
552bc4c— close the prefill gap. Vectorised thedequantize_q6_K/dequantize_iq4_xstile-staging hooks (word loads, branchless extraction,identical per-element arithmetic).
96a710c— bf16 routed experts for the official mixed-precision export.Measured (vs the Q4_K_M export)
Perplexity: wikitext-style local corpus, 8160 scored tokens, ctx 8192.
Prefill: 15K-token prompt, 6 interleaved pairs with cooldowns.
The prefill deficit was −12.4 % ±1.7 before commit
552bc4c; the tile-dequanthooks were essentially the whole gap, since they stage every
mul_mm(attention) and
mul_mm_id(routed-expert) tile.Two findings worth flagging
1.
block_q6_Kis 210 bytes, so its payload is not 4-byte aligned.Consecutive blocks alternate between 0- and 2-mod-4 addresses, making
ushortthe widest always-safe load. An earlier
uintversion of the dequant hooksilently misdecoded the misaligned half of the blocks: perplexity moved only
+0.25 %, but greedy generation degenerated into loops. Teacher-forced scoring
barely notices; autoregressive decode compounds it. Every kernel change here is
gated on bit-exact perplexity (
ppl=13.265259871on this branch) rather than a tolerance, whichis what caught it. Alignment should be derived from the block stride, not the
field offset —
block_iq4_xs(136 B) keeps 32-bit loads for that reason.2. The three mixed-precision exports rank in a surprising order. Same
corpus, same settings:
Q4_K_MMyric/…-APEX-GGUFi-qualityQ4_K_Mx40-BF16x8The community APEX build edges out the official mixed-precision build by
1.0 % while being 23 % smaller. The two recipes make opposite
bets: APEX raises precision on the edge layers (q5_k/q6_k on layers 1-9 and
38-47) and compresses the middle to iq4_xs, while the official build leaves
layers 1-39 at q4_k and raises only the last eight to bf16. On this corpus the
edge-weighted allocation wins, which is consistent with quantisation error
mattering more in early layers than late ones.
Sizing note for 128 GB machines: the official build plans 89.88 GiB at ctx
8192 and roughly 107 GiB at 256K, and Laguna has no
--ssd-streamingfallback (
--ssd-streaming is not implemented for Laguna S 2.1 yet). It needsa mostly idle machine — a first attempt with ~30 GiB held by other
applications thrashed and never became resident. Since it now ships under the
same
laguna-s-2.1-Q4_K_M.gguffilename as the 63.6 GiB build it replaced,users re-pulling "Q4_K_M" get a substantially larger model than before.
Notes for reviewers
(existing
ds4_gpu_set_tensor_matmul_suppressed(true)call and itsroute-stability comment). The Q6_K MPP direct-RHS instantiations added here
are consequently dormant on that path by design; they engage wherever MPP is
otherwise permitted.
context_lengthdisagrees withoriginal_context_length × factorisrejected with a diagnostic instead of loading.
new type does not disturb existing paths.
51-57 t/s,
Q4_K_M52-54 t/s. bf16 needs no unpacking at all, so it ismarginally the fastest per token despite being the largest to stream.
Related
706fa69revision pinned indownload_model.shreproduced the looping /"never emits the tool call" behaviour that revision
e2ccc05fixes. Weightsare identical between the two (416-byte file delta; perplexity agrees to nine
significant digits on the same build); only the chat template differs, by 121 lines including
enable_thinkingdefaultfalse→true. With the stale artifact a thinkingagent run never produced output; with the corrected one it succeeded in 3 of
4 runs. Worth merging.
sweep-style workloads prefill far past the 512-row window, so it likely
affects the same users.