is_string type info and unset generated flag for lambda - #61
Merged
Conversation
aleksisch
pushed a commit
to aleksisch/daScript
that referenced
this pull request
Dec 9, 2025
Ensure everything works
borisbat
added a commit
that referenced
this pull request
Aug 30, 2026
…12 4.93x llama.cpp The first CPU arm written under the llama.cpp side-by-side rule (LAWS 2026-08-30): their kernel's techniques mapped onto our lattice and raced by the probe. The tile rides the panel route - unpack_iq3s_panel_grp expands grid words + signs into the k5/k6 byte panel per group (one i32 store per grid word, sign nibble through a 16-entry mask table, negate (w ^ m) + (m & 0x01010101); magnitudes odd 1..15, no cross-byte carry) - and the gemv gathers each superblock into an alloca panel through an emitted per-row loop (emit_iq3s_gather; the grid and mask live as private [512 x i32]/[16 x i32] module constants). Both ride emit_block_iq4xs's sign-trick lattice with panel loads in place of the nibble+LUT; the reference tile body flips to the panel dot (kq_grp_row_dot_b fmt 33) since the batch cell now hands it the unpacked panel. Also fixed in passing, both found by this arm: - emit_slice recorded the SAVED body/tails block handles as phi incoming blocks; a block-splitting emitter (the gather loop) leaves the builder in its continuation block, so the back edges were malformed. Now captures LLVMGetInsertBlock at the branch points - identical for every non-splitting emitter. - HOW_TO QUIRK 21: an emitter-arm edit does NOT invalidate the JIT DLL cache (generator bodies are not in the hash) - three fix rounds ran stale stamps byte-identically before the cache-hit line gave it away. rm -rf .jitted_scripts after any emitter change. Gates: probe test mode GEN TUNE TEST OK - every k33 perm 1.9e-6 incl the stamped maddubs mr8 pair. Side by side, zen2 16t vs llama.cpp b10660 clean-cpu: pp512 516.9 +- 8.4 vs 104.9 (4.93x - the panel amortizes one gather across the 4-token tile; their nrc=1 kernel re-gathers per token), tg128 52.4 +- 1.0 vs 57.0 (0.92x; the no-panel gemv spelling is followup_general #61). Stamped e2e on the 1B IQ3_M: 63/64 greedy ids (the flip is the final token - the stamped near-tie class), gen 44 t/s from 23 on the reference bodies. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
borisbat
added a commit
that referenced
this pull request
Aug 31, 2026
…V, tg 0.95x The last tier for the format. Blob: an "iq3ss" arm mirroring the iq4xs 20->18 split verbatim over t.iq3ss (identical strip/d addressing, so kq_scales_of is the iq4xs arm with the plane swapped), quants at sb0*104, the % 512 off gate joining the split-scale row. Kernels ride the previous commit's MSL constant tables: iq3s_gw() carries the 512-word grid, MetalKqGemvIq3s stages it as a float4[512] MAGNITUDE slab (signs applied by select) at 4 rows per simdgroup (llama.cpp's N_R0_IQ3_S), MetalKqMvIq3sT B2/B4 + MetalKqMvB8Iq3s are the iq4xs shells over the per-32-block lane map with the grid read direct, and MetalKqMulMmK45T grows an IQ3S arm (threadgroup grid under @template_gate; the chain re-nested - `} else static_if` is a parse error). Ladders, prefill gates, and the seven-format test cells follow the iq4xs rows; fixtures at fmt 33 reuse the split-form scale fill with kq_row_ref through dequant_iq3s_plane_superblock_at. The decode GEMV got a full race before shipping: eight forms at n=2048 d=8192 (gather placement x3, gather deleted, signs deleted, llama.cpp's exact geometry, row width, f4 slab) all land in 127-141 GB/s against k4's 204 and k6's 287 in the same harness - the 9-bit-index + per-nibble-sign compose is format-intrinsic on M1, and the f4 slab is the best form and ships. HOW_TO gains the race table and QUIRK 22 (judge Metal kernel levers with the kernel probe, not tg128 e2e - +-8 t/s of e2e noise swallowed the +9% winner twice). Gates on the M1 Max: test_metal_gemv_kernels 2/2, test_metal_gemm_kernels 2/2 (108s corpus), e2e decodes the coherent story at gen 227 t/s. Rows vs llama.cpp b10660 Metal (same-run, IQ3_M): pp512 3237.6 / 3344.3 (0.97x), tg128 199.4 / 209.0 (0.95x, up from 0.82x at the first cut); M1 CPU pp512 886.2 / 433.6 (2.04x), tg128 57.4 / 66.6 (0.86x - the ledgered tg tail class, followup #61/#62). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
borisbat
added a commit
that referenced
this pull request
Aug 31, 2026
… grid, format closed The fourth tier in one day, and the smallest Metal slice of the arc. Blob: the "iq3xxss" arm mirrors the iq4xs 20->18 split verbatim over t.iq3xxss; quants bind at sb0*96; the % 512 off gate and kq_fmt_gpu_supported grow the format. Kernels are the iq3s shapes with three deltas: iq3xxs_gw (the 1 KB HALVED grid through the constant-table hoisting), ksign7m (the parity sign byte - the ksigns table exists on no GPU tier), and 24-word rows with one aux word per block. The GEMV ships directly in the crowned iq3s form - float4 magnitude slab, sign selects, 4 rows per simdgroup, dispatch rows/8 (QUIRK 22's race already ran for this shape); MetalKqMvIq3xxsT B2/B4 + MetalKqMvB8Iq3xxs and the IQ3XXS mul_mm arm (a gated uint[256] grid, the static_if chain re-nested once more) follow their iq3s siblings, with every compile/release/enc ladder and test cell mirrored at fmt 34. One cross-tier fix rode along: the CPU dequant/dot strip reads went SIGNED (int8 cast) to match the GPU kernels' decode - real strips are 1..31 where the readings agree, but the shared synthetic test fills carry high-bit bytes and the Metal row-ref would have diverged from the kernels over them. test_kquant/test_kqformat stay green. Gates on the M1 Max: test_metal_gemv_kernels 2/2, test_metal_gemm_kernels 2/2 (108s corpus); the e2e decodes the SAME story stream as the CPU and Vulkan tiers at gen 218 t/s (ttft 106ms). Rows vs llama.cpp b10660 (same local requant): M1 Metal pp512 3224.0 / 3429.9 (0.94x), tg128 213.5 / 227.3 (0.94x); M1 CPU pp512 906.0 / 410.5 (2.21x), tg128 53.5 / 74.0 (0.72x); zen2 CPU pp512 507.2 / 136.0 (3.73x), tg128 56.7 / 72.6 (0.78x - with the M1 CPU row, the arc's ledgered tg-tail class, followups #60/#61). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
borisbat
added a commit
that referenced
this pull request
Aug 31, 2026
…first u64-grid format generated iq2s joins the fmt-33/34 panel form end to end: the tile leaves the packed lists and reads the byte-expanded panel (new unpack_iq2s_panel_grp - the 10-bit qs|qh index doubled into the u64 grid's low/high word pair, signs through the shared smask expansion), kq_grp_row_dot_b grows a 23 arm (SIGNED panel bytes x per-16 UNSIGNED strips under the 33/34 d fold - d pre-eighth-ed at transcode), and the gemv gathers per superblock via emit_iq2s_gather off a [2048 x i32] private grid constant. In emit_block_iq4xs the iq2 flag splits the lo/hi accumulators and loads two ZExt strip vectors per block - per-16 strips cannot share the fused 33/34 dot. Probe 11/11 k23 perms (maddubs 8.3e-7); the tuner crowns dot_maddubs_width256_mr8 verdict=beats. QUIRK 15 rerun as written: run.tune.json still pinned iq2sq8_tile_gen "reference" from Phase A, cleared by run.das --tune. Gates: test_kquant -jit 229 pass, interp 216/17 skips, kqformat 18/18, M1 probe + kquant -jit 232/1, lint 0. E2e stamped: gen 41 -> 47 t/s; the fork vs llama.cpp moves step 10 -> 5, a 0.211-logit top-2 near-tie (stamped folds move the flip point, not the class). zen2 16t vs clean-cpu, the i1 vehicle: pp512 501.5 vs 138.5 (3.62x), tg128 55.8 vs 73.5 (0.76x - the ledgered #60/#61 CPU-decode tail). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
borisbat
added a commit
that referenced
this pull request
Aug 31, 2026
…s the constant-table hoisting The u64 grid ships as iq2s_gw - an all-literal fixed_array local the 363654b hoisting lowers to a program-scope constant table - so every kernel reads it DIRECT: no threadgroup slab anywhere (an f4-expanded slab of 1024 entries would be 32 KB, past the budget; the iq3s gridf form does not scale to u64 grids). MetalKqGemvIq2s = the iq3s GEMV geometry with per-word iq3s_sw/iq3s_sx compose and per-16 UNSIGNED strips (plain byte reads, no ^128 sign trick); the B2/B4/B8 twins split dl per half; the mul_mm rides a new IQ2S arm. The "iq2ss" blob arm is iq3ss's verbatim twin ([16 strips][2B d8 tail], 18B/sb); ladders across shapes/common/prefill/ layout; fill/rowref arms in the shared test helpers. Gates on the M1 Max: test_metal_gemv_kernels 2/2, test_metal_gemm_kernels 2/2, lint 0. E2e (parity --ngl 99, resident Metal decode): ids 40/64 vs llama.cpp - the fork at step 40 is a 0.0654-logit top-2 near-tie, the arc's deepest match, on the same story stream as the CPU-JIT tier. Four-tier table (vs llama.cpp b10660, the i1 vehicle): zen2 3.62x/0.76x, 5060 Vulkan 0.70x/0.81x, M1 CPU 2.14x/0.73x, M1 Metal 0.93x/0.93x - the CPU/Vulkan tg tails are the ledgered #60/#61 class. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
borisbat
added a commit
that referenced
this pull request
Sep 1, 2026
…12 4.93x llama.cpp The first CPU arm written under the llama.cpp side-by-side rule (LAWS 2026-08-30): their kernel's techniques mapped onto our lattice and raced by the probe. The tile rides the panel route - unpack_iq3s_panel_grp expands grid words + signs into the k5/k6 byte panel per group (one i32 store per grid word, sign nibble through a 16-entry mask table, negate (w ^ m) + (m & 0x01010101); magnitudes odd 1..15, no cross-byte carry) - and the gemv gathers each superblock into an alloca panel through an emitted per-row loop (emit_iq3s_gather; the grid and mask live as private [512 x i32]/[16 x i32] module constants). Both ride emit_block_iq4xs's sign-trick lattice with panel loads in place of the nibble+LUT; the reference tile body flips to the panel dot (kq_grp_row_dot_b fmt 33) since the batch cell now hands it the unpacked panel. Also fixed in passing, both found by this arm: - emit_slice recorded the SAVED body/tails block handles as phi incoming blocks; a block-splitting emitter (the gather loop) leaves the builder in its continuation block, so the back edges were malformed. Now captures LLVMGetInsertBlock at the branch points - identical for every non-splitting emitter. - HOW_TO QUIRK 21: an emitter-arm edit does NOT invalidate the JIT DLL cache (generator bodies are not in the hash) - three fix rounds ran stale stamps byte-identically before the cache-hit line gave it away. rm -rf .jitted_scripts after any emitter change. Gates: probe test mode GEN TUNE TEST OK - every k33 perm 1.9e-6 incl the stamped maddubs mr8 pair. Side by side, zen2 16t vs llama.cpp b10660 clean-cpu: pp512 516.9 +- 8.4 vs 104.9 (4.93x - the panel amortizes one gather across the 4-token tile; their nrc=1 kernel re-gathers per token), tg128 52.4 +- 1.0 vs 57.0 (0.92x; the no-panel gemv spelling is followup_general #61). Stamped e2e on the 1B IQ3_M: 63/64 greedy ids (the flip is the final token - the stamped near-tie class), gen 44 t/s from 23 on the reference bodies. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
borisbat
added a commit
that referenced
this pull request
Sep 1, 2026
…V, tg 0.95x The last tier for the format. Blob: an "iq3ss" arm mirroring the iq4xs 20->18 split verbatim over t.iq3ss (identical strip/d addressing, so kq_scales_of is the iq4xs arm with the plane swapped), quants at sb0*104, the % 512 off gate joining the split-scale row. Kernels ride the previous commit's MSL constant tables: iq3s_gw() carries the 512-word grid, MetalKqGemvIq3s stages it as a float4[512] MAGNITUDE slab (signs applied by select) at 4 rows per simdgroup (llama.cpp's N_R0_IQ3_S), MetalKqMvIq3sT B2/B4 + MetalKqMvB8Iq3s are the iq4xs shells over the per-32-block lane map with the grid read direct, and MetalKqMulMmK45T grows an IQ3S arm (threadgroup grid under @template_gate; the chain re-nested - `} else static_if` is a parse error). Ladders, prefill gates, and the seven-format test cells follow the iq4xs rows; fixtures at fmt 33 reuse the split-form scale fill with kq_row_ref through dequant_iq3s_plane_superblock_at. The decode GEMV got a full race before shipping: eight forms at n=2048 d=8192 (gather placement x3, gather deleted, signs deleted, llama.cpp's exact geometry, row width, f4 slab) all land in 127-141 GB/s against k4's 204 and k6's 287 in the same harness - the 9-bit-index + per-nibble-sign compose is format-intrinsic on M1, and the f4 slab is the best form and ships. HOW_TO gains the race table and QUIRK 22 (judge Metal kernel levers with the kernel probe, not tg128 e2e - +-8 t/s of e2e noise swallowed the +9% winner twice). Gates on the M1 Max: test_metal_gemv_kernels 2/2, test_metal_gemm_kernels 2/2 (108s corpus), e2e decodes the coherent story at gen 227 t/s. Rows vs llama.cpp b10660 Metal (same-run, IQ3_M): pp512 3237.6 / 3344.3 (0.97x), tg128 199.4 / 209.0 (0.95x, up from 0.82x at the first cut); M1 CPU pp512 886.2 / 433.6 (2.04x), tg128 57.4 / 66.6 (0.86x - the ledgered tg tail class, followup #61/#62). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
borisbat
added a commit
that referenced
this pull request
Sep 1, 2026
… grid, format closed The fourth tier in one day, and the smallest Metal slice of the arc. Blob: the "iq3xxss" arm mirrors the iq4xs 20->18 split verbatim over t.iq3xxss; quants bind at sb0*96; the % 512 off gate and kq_fmt_gpu_supported grow the format. Kernels are the iq3s shapes with three deltas: iq3xxs_gw (the 1 KB HALVED grid through the constant-table hoisting), ksign7m (the parity sign byte - the ksigns table exists on no GPU tier), and 24-word rows with one aux word per block. The GEMV ships directly in the crowned iq3s form - float4 magnitude slab, sign selects, 4 rows per simdgroup, dispatch rows/8 (QUIRK 22's race already ran for this shape); MetalKqMvIq3xxsT B2/B4 + MetalKqMvB8Iq3xxs and the IQ3XXS mul_mm arm (a gated uint[256] grid, the static_if chain re-nested once more) follow their iq3s siblings, with every compile/release/enc ladder and test cell mirrored at fmt 34. One cross-tier fix rode along: the CPU dequant/dot strip reads went SIGNED (int8 cast) to match the GPU kernels' decode - real strips are 1..31 where the readings agree, but the shared synthetic test fills carry high-bit bytes and the Metal row-ref would have diverged from the kernels over them. test_kquant/test_kqformat stay green. Gates on the M1 Max: test_metal_gemv_kernels 2/2, test_metal_gemm_kernels 2/2 (108s corpus); the e2e decodes the SAME story stream as the CPU and Vulkan tiers at gen 218 t/s (ttft 106ms). Rows vs llama.cpp b10660 (same local requant): M1 Metal pp512 3224.0 / 3429.9 (0.94x), tg128 213.5 / 227.3 (0.94x); M1 CPU pp512 906.0 / 410.5 (2.21x), tg128 53.5 / 74.0 (0.72x); zen2 CPU pp512 507.2 / 136.0 (3.73x), tg128 56.7 / 72.6 (0.78x - with the M1 CPU row, the arc's ledgered tg-tail class, followups #60/#61). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
borisbat
added a commit
that referenced
this pull request
Sep 1, 2026
…first u64-grid format generated iq2s joins the fmt-33/34 panel form end to end: the tile leaves the packed lists and reads the byte-expanded panel (new unpack_iq2s_panel_grp - the 10-bit qs|qh index doubled into the u64 grid's low/high word pair, signs through the shared smask expansion), kq_grp_row_dot_b grows a 23 arm (SIGNED panel bytes x per-16 UNSIGNED strips under the 33/34 d fold - d pre-eighth-ed at transcode), and the gemv gathers per superblock via emit_iq2s_gather off a [2048 x i32] private grid constant. In emit_block_iq4xs the iq2 flag splits the lo/hi accumulators and loads two ZExt strip vectors per block - per-16 strips cannot share the fused 33/34 dot. Probe 11/11 k23 perms (maddubs 8.3e-7); the tuner crowns dot_maddubs_width256_mr8 verdict=beats. QUIRK 15 rerun as written: run.tune.json still pinned iq2sq8_tile_gen "reference" from Phase A, cleared by run.das --tune. Gates: test_kquant -jit 229 pass, interp 216/17 skips, kqformat 18/18, M1 probe + kquant -jit 232/1, lint 0. E2e stamped: gen 41 -> 47 t/s; the fork vs llama.cpp moves step 10 -> 5, a 0.211-logit top-2 near-tie (stamped folds move the flip point, not the class). zen2 16t vs clean-cpu, the i1 vehicle: pp512 501.5 vs 138.5 (3.62x), tg128 55.8 vs 73.5 (0.76x - the ledgered #60/#61 CPU-decode tail). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
borisbat
added a commit
that referenced
this pull request
Sep 1, 2026
…s the constant-table hoisting The u64 grid ships as iq2s_gw - an all-literal fixed_array local the 363654b hoisting lowers to a program-scope constant table - so every kernel reads it DIRECT: no threadgroup slab anywhere (an f4-expanded slab of 1024 entries would be 32 KB, past the budget; the iq3s gridf form does not scale to u64 grids). MetalKqGemvIq2s = the iq3s GEMV geometry with per-word iq3s_sw/iq3s_sx compose and per-16 UNSIGNED strips (plain byte reads, no ^128 sign trick); the B2/B4/B8 twins split dl per half; the mul_mm rides a new IQ2S arm. The "iq2ss" blob arm is iq3ss's verbatim twin ([16 strips][2B d8 tail], 18B/sb); ladders across shapes/common/prefill/ layout; fill/rowref arms in the shared test helpers. Gates on the M1 Max: test_metal_gemv_kernels 2/2, test_metal_gemm_kernels 2/2, lint 0. E2e (parity --ngl 99, resident Metal decode): ids 40/64 vs llama.cpp - the fork at step 40 is a 0.0654-logit top-2 near-tie, the arc's deepest match, on the same story stream as the CPU-JIT tier. Four-tier table (vs llama.cpp b10660, the i1 vehicle): zen2 3.62x/0.76x, 5060 Vulkan 0.70x/0.81x, M1 CPU 2.14x/0.73x, M1 Metal 0.93x/0.93x - the CPU/Vulkan tg tails are the ledgered #60/#61 class. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
borisbat
added a commit
that referenced
this pull request
Sep 1, 2026
…12 4.93x llama.cpp The first CPU arm written under the llama.cpp side-by-side rule (LAWS 2026-08-30): their kernel's techniques mapped onto our lattice and raced by the probe. The tile rides the panel route - unpack_iq3s_panel_grp expands grid words + signs into the k5/k6 byte panel per group (one i32 store per grid word, sign nibble through a 16-entry mask table, negate (w ^ m) + (m & 0x01010101); magnitudes odd 1..15, no cross-byte carry) - and the gemv gathers each superblock into an alloca panel through an emitted per-row loop (emit_iq3s_gather; the grid and mask live as private [512 x i32]/[16 x i32] module constants). Both ride emit_block_iq4xs's sign-trick lattice with panel loads in place of the nibble+LUT; the reference tile body flips to the panel dot (kq_grp_row_dot_b fmt 33) since the batch cell now hands it the unpacked panel. Also fixed in passing, both found by this arm: - emit_slice recorded the SAVED body/tails block handles as phi incoming blocks; a block-splitting emitter (the gather loop) leaves the builder in its continuation block, so the back edges were malformed. Now captures LLVMGetInsertBlock at the branch points - identical for every non-splitting emitter. - HOW_TO QUIRK 21: an emitter-arm edit does NOT invalidate the JIT DLL cache (generator bodies are not in the hash) - three fix rounds ran stale stamps byte-identically before the cache-hit line gave it away. rm -rf .jitted_scripts after any emitter change. Gates: probe test mode GEN TUNE TEST OK - every k33 perm 1.9e-6 incl the stamped maddubs mr8 pair. Side by side, zen2 16t vs llama.cpp b10660 clean-cpu: pp512 516.9 +- 8.4 vs 104.9 (4.93x - the panel amortizes one gather across the 4-token tile; their nrc=1 kernel re-gathers per token), tg128 52.4 +- 1.0 vs 57.0 (0.92x; the no-panel gemv spelling is followup_general `#61`). Stamped e2e on the 1B IQ3_M: 63/64 greedy ids (the flip is the final token - the stamped near-tie class), gen 44 t/s from 23 on the reference bodies. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
borisbat
added a commit
that referenced
this pull request
Sep 1, 2026
…V, tg 0.95x The last tier for the format. Blob: an "iq3ss" arm mirroring the iq4xs 20->18 split verbatim over t.iq3ss (identical strip/d addressing, so kq_scales_of is the iq4xs arm with the plane swapped), quants at sb0*104, the % 512 off gate joining the split-scale row. Kernels ride the previous commit's MSL constant tables: iq3s_gw() carries the 512-word grid, MetalKqGemvIq3s stages it as a float4[512] MAGNITUDE slab (signs applied by select) at 4 rows per simdgroup (llama.cpp's N_R0_IQ3_S), MetalKqMvIq3sT B2/B4 + MetalKqMvB8Iq3s are the iq4xs shells over the per-32-block lane map with the grid read direct, and MetalKqMulMmK45T grows an IQ3S arm (threadgroup grid under @template_gate; the chain re-nested - `} else static_if` is a parse error). Ladders, prefill gates, and the seven-format test cells follow the iq4xs rows; fixtures at fmt 33 reuse the split-form scale fill with kq_row_ref through dequant_iq3s_plane_superblock_at. The decode GEMV got a full race before shipping: eight forms at n=2048 d=8192 (gather placement x3, gather deleted, signs deleted, llama.cpp's exact geometry, row width, f4 slab) all land in 127-141 GB/s against k4's 204 and k6's 287 in the same harness - the 9-bit-index + per-nibble-sign compose is format-intrinsic on M1, and the f4 slab is the best form and ships. HOW_TO gains the race table and QUIRK 22 (judge Metal kernel levers with the kernel probe, not tg128 e2e - +-8 t/s of e2e noise swallowed the +9% winner twice). Gates on the M1 Max: test_metal_gemv_kernels 2/2, test_metal_gemm_kernels 2/2 (108s corpus), e2e decodes the coherent story at gen 227 t/s. Rows vs llama.cpp b10660 Metal (same-run, IQ3_M): pp512 3237.6 / 3344.3 (0.97x), tg128 199.4 / 209.0 (0.95x, up from 0.82x at the first cut); M1 CPU pp512 886.2 / 433.6 (2.04x), tg128 57.4 / 66.6 (0.86x - the ledgered tg tail class, followup `#61`/`#62`). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
borisbat
added a commit
that referenced
this pull request
Sep 1, 2026
… grid, format closed The fourth tier in one day, and the smallest Metal slice of the arc. Blob: the "iq3xxss" arm mirrors the iq4xs 20->18 split verbatim over t.iq3xxss; quants bind at sb0*96; the % 512 off gate and kq_fmt_gpu_supported grow the format. Kernels are the iq3s shapes with three deltas: iq3xxs_gw (the 1 KB HALVED grid through the constant-table hoisting), ksign7m (the parity sign byte - the ksigns table exists on no GPU tier), and 24-word rows with one aux word per block. The GEMV ships directly in the crowned iq3s form - float4 magnitude slab, sign selects, 4 rows per simdgroup, dispatch rows/8 (QUIRK 22's race already ran for this shape); MetalKqMvIq3xxsT B2/B4 + MetalKqMvB8Iq3xxs and the IQ3XXS mul_mm arm (a gated uint[256] grid, the static_if chain re-nested once more) follow their iq3s siblings, with every compile/release/enc ladder and test cell mirrored at fmt 34. One cross-tier fix rode along: the CPU dequant/dot strip reads went SIGNED (int8 cast) to match the GPU kernels' decode - real strips are 1..31 where the readings agree, but the shared synthetic test fills carry high-bit bytes and the Metal row-ref would have diverged from the kernels over them. test_kquant/test_kqformat stay green. Gates on the M1 Max: test_metal_gemv_kernels 2/2, test_metal_gemm_kernels 2/2 (108s corpus); the e2e decodes the SAME story stream as the CPU and Vulkan tiers at gen 218 t/s (ttft 106ms). Rows vs llama.cpp b10660 (same local requant): M1 Metal pp512 3224.0 / 3429.9 (0.94x), tg128 213.5 / 227.3 (0.94x); M1 CPU pp512 906.0 / 410.5 (2.21x), tg128 53.5 / 74.0 (0.72x); zen2 CPU pp512 507.2 / 136.0 (3.73x), tg128 56.7 / 72.6 (0.78x - with the M1 CPU row, the arc's ledgered tg-tail class, followups `#60`/`#61`). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
borisbat
added a commit
that referenced
this pull request
Sep 1, 2026
…first u64-grid format generated iq2s joins the fmt-33/34 panel form end to end: the tile leaves the packed lists and reads the byte-expanded panel (new unpack_iq2s_panel_grp - the 10-bit qs|qh index doubled into the u64 grid's low/high word pair, signs through the shared smask expansion), kq_grp_row_dot_b grows a 23 arm (SIGNED panel bytes x per-16 UNSIGNED strips under the 33/34 d fold - d pre-eighth-ed at transcode), and the gemv gathers per superblock via emit_iq2s_gather off a [2048 x i32] private grid constant. In emit_block_iq4xs the iq2 flag splits the lo/hi accumulators and loads two ZExt strip vectors per block - per-16 strips cannot share the fused 33/34 dot. Probe 11/11 k23 perms (maddubs 8.3e-7); the tuner crowns dot_maddubs_width256_mr8 verdict=beats. QUIRK 15 rerun as written: run.tune.json still pinned iq2sq8_tile_gen "reference" from Phase A, cleared by run.das --tune. Gates: test_kquant -jit 229 pass, interp 216/17 skips, kqformat 18/18, M1 probe + kquant -jit 232/1, lint 0. E2e stamped: gen 41 -> 47 t/s; the fork vs llama.cpp moves step 10 -> 5, a 0.211-logit top-2 near-tie (stamped folds move the flip point, not the class). zen2 16t vs clean-cpu, the i1 vehicle: pp512 501.5 vs 138.5 (3.62x), tg128 55.8 vs 73.5 (0.76x - the ledgered `#60`/`#61` CPU-decode tail). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
borisbat
added a commit
that referenced
this pull request
Sep 1, 2026
…s the constant-table hoisting The u64 grid ships as iq2s_gw - an all-literal fixed_array local the 363654b hoisting lowers to a program-scope constant table - so every kernel reads it DIRECT: no threadgroup slab anywhere (an f4-expanded slab of 1024 entries would be 32 KB, past the budget; the iq3s gridf form does not scale to u64 grids). MetalKqGemvIq2s = the iq3s GEMV geometry with per-word iq3s_sw/iq3s_sx compose and per-16 UNSIGNED strips (plain byte reads, no ^128 sign trick); the B2/B4/B8 twins split dl per half; the mul_mm rides a new IQ2S arm. The "iq2ss" blob arm is iq3ss's verbatim twin ([16 strips][2B d8 tail], 18B/sb); ladders across shapes/common/prefill/ layout; fill/rowref arms in the shared test helpers. Gates on the M1 Max: test_metal_gemv_kernels 2/2, test_metal_gemm_kernels 2/2, lint 0. E2e (parity --ngl 99, resident Metal decode): ids 40/64 vs llama.cpp - the fork at step 40 is a 0.0654-logit top-2 near-tie, the arc's deepest match, on the same story stream as the CPU-JIT tier. Four-tier table (vs llama.cpp b10660, the i1 vehicle): zen2 3.62x/0.76x, 5060 Vulkan 0.70x/0.81x, M1 CPU 2.14x/0.73x, M1 Metal 0.93x/0.93x - the CPU/Vulkan tg tails are the ledgered `#60`/`#61` class. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
No description provided.