nx_q4k_matmul_x4_gate.nx
buildroot/runtime/nx_q4k_matmul_x4_gate.nx
about
nx_q4k_matmul_x4_gate.nx -- adversarial gate for the PACKED-SIMD
Q4_K matmul paths (nx_f32_q4k_matmul_x4 / _pool_x4) against the
scalar serial oracle nx_f32_q4k_matmul.
NUMERIC REGIME: the x4 path sums each output cell as left-to-right
4-lane dot chunks -- a different f32 rounding order than scalar.
This gate therefore constructs data where EVERY intermediate sum is
an integer with |sum| < 2^24, so f32 addition is EXACT regardless
of order and bit-exact comparison across ALL paths is legitimate:
* weights: dense synthetic Q4_K blocks with d=1.0 (f16 0x3C00),
dmin=0, all 6-bit scales=1, mins=0, LCG nibble bytes -> every
dequantized value is an exact integer 0..15;
* A: exact small-int f32 (nx_i32_to_f32 of LCG ints).
k=512 lanes, |A|<=512, w<=15 -> |cell| <= 512*15*512 = 3.9M < 2^24.
Big shape k=1024, |A|<=512 -> <= 7.9M < 2^24. Exact.
(ULP-divergent real-model fidelity is witnessed separately by the
argmax probe -- " Paris" -- after the dispatcher flip.)
pool-x4 vs serial-x4 equality holds on ANY data (identical per-cell
order; column banding never splits a cell) -- asserted here too.
Checks (10):
1 scalar serial oracle OK (m=3, k=512, n=37 -- prime n)
2 serial-x4 == scalar bit-exact
3 pool-x4 (auto pool) == serial-x4 bit-exact
4 pool-x4 (3-worker pool, odd banding) == serial-x4
5 pool reuse: second call, new A, same pool == fresh serial-x4
6 m=1 decode shape: serial-x4 == scalar
7 wide-A (+-512 ints): serial-x4 == scalar (exact-regime bound)
8 n=1 single-column edge via pool (band clamp) == scalar
9 SPEEDUP ladder on decode shape m=1 k=1024 n=4864: serial-scalar
vs pool-scalar vs pool-x4 (all bit-exact vs each other in this
regime); floor: pool-x4 >= 2.5x serial-scalar (measured printed)
10 all three big-shape outputs bit-identical
genealogy_id: nx_f32x4_mt_matmul (5.0x packed lever) + q4k_matmul_mt_gate
lineage_id: q4k_matmul_x4_gate_v1
dependencies 3 imports · 0 importers
imports: nx_f32_q4k_matmul.nxnx_fmt.nxnx_gate_verdict.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 43 | const XG_M: i64 = 3 |
| 44 | const XG_K: i64 = 512 |
| 45 | const XG_N: i64 = 37 |
| 47 | const XB_K: i64 = 1024 |
| 48 | const XB_N: i64 = 4864 |
| 49 | const XB_REPS: i64 = 3 |
| 51 | const XG_SPEEDUP_FLOOR_X100: i64 = 250 |
functions
| 53 | func x_lcg(s: i64) -> i64 |
| 61 | func x_block_dense(buf: *u8, off: i64, seed: i64) -> i64 |
| 84 | func x_fill_weights(buf: *u8, n_rows: i64, k: i64, seed: i64) -> i64 |
| 101 | func x_fill_a(p: *i64, count: i64, seed: i64, half: i64) -> i64 |
| 113 | func x_poison(p: *i64, count: i64) -> i64 called by 1: main |
| 123 | func x_same(a: *i64, b: *i64, count: i64) -> i64 called by 1: main |
| 132 | func x_nl() -> i64 |
| 137 | func main() -> i64 |