code wiki / (root) / nx_f32_lazy_weight_test.nx

nx_f32_lazy_weight_test.nx source

↩ module page · 129 lines · 4657 B

1// nx_f32_lazy_weight_test.nx -- smoke for nx_f32_lazy_weight.nx. 2// 3// Two dispatch paths: 4// F32 path: build a 1x4 f32 weight as raw bits, do lazy_matmul, 5// verify result equals direct nx_f32_matmul output. 6// Q4_K path: build a 1x256 Q4_K super-block with known values, 7// do lazy_matmul, verify result equals direct 8// nx_f32_q4k_matmul output. 9 10import "nx_syscalls.nx" 11import "nx_tier.nx" 12import "nx_le.nx" 13import "nx_gguf_load.nx" 14import "nx_f32.nx" 15import "nx_f32_matmul.nx" 16import "nx_q4k_to_f32.nx" 17import "nx_f32_q4k_matmul.nx" 18import "nx_f32_lazy_weight.nx" 19 20func _write_block(buf: *u8, off: i64) -> i64 { 21 nx_le_write_u16(buf, off + 0, 0x3C00) // d = 1.0 22 nx_le_write_u16(buf, off + 2, 0x0000) 23 buf[off + 4] = 0x01 as u8 24 buf[off + 5] = 0x01 as u8 25 buf[off + 6] = 0x01 as u8 26 buf[off + 7] = 0x01 as u8 27 buf[off + 8] = 0 as u8 28 buf[off + 9] = 0 as u8 29 buf[off + 10] = 0 as u8 30 buf[off + 11] = 0 as u8 31 buf[off + 12] = 0x02 as u8 32 buf[off + 13] = 0 as u8 33 buf[off + 14] = 0 as u8 34 buf[off + 15] = 0 as u8 35 var z: i64 = 0 36 while z < 128 { 37 buf[off + 16 + z] = 0 as u8 38 z = z + 1 39 } 40 buf[off + 16 + 0] = 0x32 as u8 41 buf[off + 16 + 64] = 0x32 as u8 42 return off + 144 43} 44 45func main() -> i64 { 46 var vi: nx_int = 0 47 while vi < NX_LW_N_VERDICTS { 48 if nx_lw_verdict_is_valid(vi) != 1 { return 5 + vi } 49 vi = vi + 1 50 } 51 52 // ===== F32 path ===== 53 let W_f32_storage: *i64 = sys_mmap(4 * 8) as *i64 54 W_f32_storage[0] = 0x3F800000 // 1.0 55 W_f32_storage[1] = 0x40000000 // 2.0 56 W_f32_storage[2] = 0x40400000 // 3.0 57 W_f32_storage[3] = 0x40800000 // 4.0 58 59 let A1: *i64 = sys_mmap(8) as *i64 60 A1[0] = 0x40000000 // 2.0 61 62 // Direct call: A [1,1] @ B [1,4] -> C [1,4]. With A=2.0, expected: [2, 4, 6, 8]. 63 let C_direct: *i64 = sys_mmap(4 * 8) as *i64 64 nx_f32_matmul(A1, W_f32_storage, C_direct, 1, 1, 4) 65 66 // Lazy call: same inputs via dispatcher. 67 let W_lazy_f32: *NxF32LazyWeight = 68 nx_f32_lazy_weight_new_f32(W_f32_storage, 1, 4) 69 let C_lazy: *i64 = sys_mmap(4 * 8) as *i64 70 let v_f32: nx_int = nx_f32_lazy_matmul(A1, W_lazy_f32, C_lazy, 1, 1, 4) 71 if v_f32 != NX_LW_OK { return 20 + v_f32 } 72 73 // Both results must be bit-exact equal. 74 var i: nx_int = 0 75 while i < 4 { 76 if C_lazy[i] != C_direct[i] { return 30 + i } 77 i = i + 1 78 } 79 if C_lazy[0] != 0x40000000 { return 40 } // 2.0 80 if C_lazy[1] != 0x40800000 { return 41 } // 4.0 81 if C_lazy[2] != 0x40C00000 { return 42 } // 6.0 82 if C_lazy[3] != 0x41000000 { return 43 } // 8.0 83 84 // ===== Q4_K path ===== 85 // UPDATED 2026-07-07 to the organ's CURRENT axis semantics (B = n 86 // weight rows x k quantized values, k % 256 == 0). The previous 87 // k=1/n=256 shape encoded the OLD transposed layout: after the 88 // k-axis fix it tripped ERR_ALIGN, which the dispatcher then 89 // SWALLOWED (returned OK over a zero C) -- this test had been 90 // failing exit 70 unnoticed. The dispatcher now surfaces inner 91 // verdicts as NX_LW_ERR_INNER (asserted below) and routes Q4_K 92 // through the shared thread pool (nx_f32_q4k_matmul_pool). 93 let buf_q4k: *u8 = sys_mmap(256) 94 let _end: i64 = _write_block(buf_q4k, 0) 95 96 // A row: 1.0 at the block's nonzero weight positions [0,32,128]. 97 let A2: *i64 = sys_mmap(256 * 8) as *i64 98 var p: nx_int = 0 99 while p < 256 { 100 A2[p] = 0 101 p = p + 1 102 } 103 A2[0] = 0x3F800000 // 1.0 104 A2[32] = 0x3F800000 105 A2[128] = 0x3F800000 106 107 // Direct serial call: C[0] = 1*2 + 1*3 + 1*4 = 9.0. 108 let C_direct2: *i64 = sys_mmap(8) as *i64 109 let v_dir: nx_int = nx_f32_q4k_matmul(A2, buf_q4k, 0, C_direct2, 1, 256, 1) 110 if v_dir != NX_FQ4M_OK { return 45 + v_dir } 111 112 // Lazy dispatcher call (pooled path) must match bit-exactly. 113 let W_lazy_q4k: *NxF32LazyWeight = 114 nx_f32_lazy_weight_new_q4k(buf_q4k, 0, 256, 1) 115 let C_lazy2: *i64 = sys_mmap(8) as *i64 116 C_lazy2[0] = 0 - 777777 // poison 117 let v_q4k: nx_int = nx_f32_lazy_matmul(A2, W_lazy_q4k, C_lazy2, 1, 256, 1) 118 if v_q4k != NX_LW_OK { return 50 + v_q4k } 119 if C_lazy2[0] != C_direct2[0] { return 60 } 120 if C_lazy2[0] != 0x41100000 { return 70 } // 9.0 121 122 // The stale pre-axis-fix shape (k=1) must now SURFACE as 123 // NX_LW_ERR_INNER (inner ERR_ALIGN), not silently return OK. 124 let C_bad: *i64 = sys_mmap(8) as *i64 125 let v_bad: nx_int = nx_f32_lazy_matmul(A2, W_lazy_q4k, C_bad, 1, 1, 256) 126 if v_bad != NX_LW_ERR_INNER { return 75 } 127 128 return 0 129}