code wiki / (root) / nx_lw_cache_gate.nx

nx_lw_cache_gate.nx source

↩ module page · 321 lines · 12318 B

1// nx_lw_cache_gate.nx -- gate for the packed dequant-once cache in 2// nx_f32_lazy_weight (the m=1 decode lever: stop re-dequanting the 3// same weights every token; cached matmuls are pure packed 4// __f32x4_dot bands). 5// 6// Exact-f32 regime construction as in nx_q4k_matmul_x4_gate (dense 7// d=1.0/sc=1 blocks -> integer dequant values 0..15; int A; all 8// |sums| < 2^24), so bit-exact comparison between the CACHED path 9// (x4 dot order) and the scalar streaming oracle is legitimate. 10// 11// Checks (8): 12// 1 scalar oracle OK (k=512, n=37, m=3) 13// 2 first dispatch fills + matches oracle; pk_state=1; used bytes exact 14// 3 second dispatch (new A) matches fresh oracle (cache reuse + 15// shared-pool delta-wait across fill+dot submissions) 16// 4 m=1 decode shape via dispatcher matches oracle 17// 5 budget refusal: fresh weight + tiny budget -> pk_state=-1 AND 18// result still matches oracle (streamed scalar-pool fallback) 19// 6 stale k=1 shape surfaces NX_LW_ERR_INNER (guard before cache) 20// 7 decode-shape speedup: cached reps vs streamed reps (same data, 21// bit-exact) -- floor cached >= 1.5x streamed; first-call fill 22// overhead printed for the honest record 23// 8 cached and streamed big-shape outputs bit-identical 24// 25// lineage_id: lw_cache_gate_v1 26 27import "nx_gate_verdict.nx" 28import "nx_f32_lazy_weight.nx" 29import "nx_fmt.nx" 30 31const LG_M: i64 = 3 32const LG_K: i64 = 512 33const LG_N: i64 = 37 34 35const LB_K: i64 = 1024 36const LB_N: i64 = 4864 37const LB_REPS: i64 = 3 38 39const LG_SPEEDUP_FLOOR_X100: i64 = 150 40 41func l_lcg(s: i64) -> i64 { 42 var v: i64 = s * 1103515245 + 12345 43 v = v & 2147483647 44 return v 45} 46 47func l_block_dense(buf: *u8, off: i64, seed: i64) -> i64 { 48 buf[off + 0] = 0x00 as u8 49 buf[off + 1] = 0x3C as u8 50 buf[off + 2] = 0 as u8 51 buf[off + 3] = 0 as u8 52 var i: i64 = 0 53 while i < 4 { 54 buf[off + 4 + i] = 0x01 as u8 55 buf[off + 8 + i] = 0x00 as u8 56 buf[off + 12 + i] = 0x01 as u8 57 i = i + 1 58 } 59 var s: i64 = seed 60 var z: i64 = 0 61 while z < 128 { 62 s = l_lcg(s) 63 buf[off + 16 + z] = (s & 255) as u8 64 z = z + 1 65 } 66 return off + 144 67} 68 69func l_fill_weights(buf: *u8, n_rows: i64, k: i64, seed: i64) -> i64 { 70 let bpr: i64 = (k / 256) * 144 71 var s: i64 = seed 72 var r: i64 = 0 73 while r < n_rows { 74 var b: i64 = 0 75 while b < k / 256 { 76 s = l_lcg(s) 77 l_block_dense(buf, r * bpr + b * 144, s) 78 b = b + 1 79 } 80 r = r + 1 81 } 82 return 0 83} 84 85func l_fill_a(p: *i64, count: i64, seed: i64, half: i64) -> i64 { 86 var s: i64 = seed 87 var i: i64 = 0 88 while i < count { 89 s = l_lcg(s) 90 let v: i64 = (s % (half + half)) - half 91 p[i] = nx_i32_to_f32(v) 92 i = i + 1 93 } 94 return 0 95} 96 97func l_poison(p: *i64, count: i64) -> i64 { 98 let pv: i64 = 0 - 777777 99 var i: i64 = 0 100 while i < count { 101 p[i] = pv 102 i = i + 1 103 } 104 return 0 105} 106 107func l_same(a: *i64, b: *i64, count: i64) -> i64 { 108 var i: i64 = 0 109 while i < count { 110 if a[i] != b[i] { return 0 } 111 i = i + 1 112 } 113 return 1 114} 115 116func l_nl() -> i64 { 117 fmt_puts("\n" as *u8) 118 return 0 119} 120 121func lwc_run() -> i64 { 122 let a_n: i64 = LG_M * LG_K 123 let b_n: i64 = LG_N * (LG_K / 256) * 144 124 let c_n: i64 = LG_M * LG_N 125 let A: *i64 = sys_mmap(a_n * 8) as *i64 126 let B: *u8 = sys_mmap(b_n) 127 let Cs: *i64 = sys_mmap(c_n * 8) as *i64 128 let Cd: *i64 = sys_mmap(c_n * 8) as *i64 129 l_fill_a(A, a_n, 20260708, 5) 130 l_fill_weights(B, LG_N, LG_K, 424242) 131 132 var pass: i64 = 0 133 134 // GATE REPAIR 2026-08-01: NX_LW_CACHE_BUDGET_DEFAULT is now 0 ("stream quantized weights", 135 // re-measured by the budget owner the same day). Under a 0 default, tooth 2's pk_state==1 136 // can never hold -- the gate was failing against the UNMODIFIED lib, for a reason unrelated 137 // to any kernel change. This gate's job is to prove the cache machinery CORRECT WHEN ENABLED, 138 // not to pin the production default (that is the budget owner's measured call), so the cache 139 // teeth run under an EXPLICIT test budget. Production keeps default=0 untouched. 140 nx_lw_set_cache_budget(1073741824) 141 142 // ---- 1: scalar oracle ---- 143 let v1: nx_int = nx_f32_q4k_matmul(A, B, 0, Cs, LG_M, LG_K, LG_N) 144 if v1 != NX_FQ4M_OK { fmt_puts("LWC 1 ORACLE FAIL"); l_nl(); return 11 } 145 fmt_puts("LWC 1 ORACLE OK"); l_nl() 146 pass = pass + 1 147 148 // ---- 2: first dispatch fills the cache + matches ---- 149 let W: *NxF32LazyWeight = nx_f32_lazy_weight_new_q4k(B, 0, LG_K, LG_N) 150 l_poison(Cd, c_n) 151 let v2: nx_int = nx_f32_lazy_matmul(A, W, Cd, LG_M, LG_K, LG_N) 152 var ok2: i64 = 0 153 if v2 == NX_LW_OK { if W.pk_state == 1 { ok2 = l_same(Cd, Cs, c_n) } } 154 let want_used: i64 = LG_N * LG_K * 4 155 if nx_lw_cache_used() != want_used { ok2 = 0 } 156 if ok2 != 1 { fmt_puts("LWC 2 FILL FAIL"); l_nl(); return 12 } 157 fmt_puts("LWC 2 FILL+MATCH OK used="); fmt_putn(nx_lw_cache_used()); l_nl() 158 pass = pass + 1 159 160 // ---- 3: cache reuse with new A ---- 161 l_fill_a(A, a_n, 555008, 5) 162 let v3s: nx_int = nx_f32_q4k_matmul(A, B, 0, Cs, LG_M, LG_K, LG_N) 163 if v3s != NX_FQ4M_OK { return 13 } 164 l_poison(Cd, c_n) 165 let v3: nx_int = nx_f32_lazy_matmul(A, W, Cd, LG_M, LG_K, LG_N) 166 var ok3: i64 = 0 167 if v3 == NX_LW_OK { ok3 = l_same(Cd, Cs, c_n) } 168 if ok3 != 1 { fmt_puts("LWC 3 REUSE FAIL"); l_nl(); return 13 } 169 fmt_puts("LWC 3 REUSE OK"); l_nl() 170 pass = pass + 1 171 172 // ---- 4: m=1 decode shape ---- 173 let c1s: *i64 = sys_mmap(LG_N * 8) as *i64 174 let c1d: *i64 = sys_mmap(LG_N * 8) as *i64 175 let v4s: nx_int = nx_f32_q4k_matmul(A, B, 0, c1s, 1, LG_K, LG_N) 176 l_poison(c1d, LG_N) 177 let v4: nx_int = nx_f32_lazy_matmul(A, W, c1d, 1, LG_K, LG_N) 178 var ok4: i64 = 0 179 if v4s == NX_FQ4M_OK { if v4 == NX_LW_OK { ok4 = l_same(c1d, c1s, LG_N) } } 180 if ok4 != 1 { fmt_puts("LWC 4 M1 FAIL"); l_nl(); return 14 } 181 fmt_puts("LWC 4 M1 OK"); l_nl() 182 pass = pass + 1 183 184 // ---- 5: budget refusal -> streamed fallback still correct ---- 185 nx_lw_set_cache_budget(nx_lw_cache_used() + 1) 186 let W2: *NxF32LazyWeight = nx_f32_lazy_weight_new_q4k(B, 0, LG_K, LG_N) 187 l_poison(Cd, c_n) 188 let v5: nx_int = nx_f32_lazy_matmul(A, W2, Cd, LG_M, LG_K, LG_N) 189 var ok5: i64 = 0 190 if v5 == NX_LW_OK { if W2.pk_state == 0 - 1 { ok5 = l_same(Cd, Cs, c_n) } } 191 if ok5 != 1 { fmt_puts("LWC 5 BUDGET-REFUSE FAIL"); l_nl(); return 15 } 192 fmt_puts("LWC 5 BUDGET-REFUSE+STREAM OK"); l_nl() 193 pass = pass + 1 194 195 // ---- 6: stale k=1 shape surfaces ERR_INNER ---- 196 let v6: nx_int = nx_f32_lazy_matmul(A, W, Cd, 1, 1, 256) 197 if v6 != NX_LW_ERR_INNER { fmt_puts("LWC 6 STALE-GUARD FAIL"); l_nl(); return 16 } 198 fmt_puts("LWC 6 STALE-GUARD OK"); l_nl() 199 pass = pass + 1 200 201 // ---- 7+8: decode-shape speedup, cached vs streamed ---- 202 let bb_n: i64 = LB_N * (LB_K / 256) * 144 203 let BA: *i64 = sys_mmap(LB_K * 8) as *i64 204 let BB: *u8 = sys_mmap(bb_n) 205 let BCs: *i64 = sys_mmap(LB_N * 8) as *i64 206 let BCc: *i64 = sys_mmap(LB_N * 8) as *i64 207 l_fill_a(BA, LB_K, 7788, 512) 208 l_fill_weights(BB, LB_N, LB_K, 313373) 209 210 // streamed reference: force refusal with a tiny budget 211 nx_lw_set_cache_budget(1) 212 let Wstream: *NxF32LazyWeight = nx_f32_lazy_weight_new_q4k(BB, 0, LB_K, LB_N) 213 l_poison(BCs, LB_N) 214 let t0: i64 = sys_now_us() 215 var r0: i64 = 0 216 while r0 < LB_REPS { 217 let vs: nx_int = nx_f32_lazy_matmul(BA, Wstream, BCs, 1, LB_K, LB_N) 218 if vs != NX_LW_OK { return 21 } 219 r0 = r0 + 1 220 } 221 let us_stream: i64 = (sys_now_us() - t0) / LB_REPS 222 if Wstream.pk_state != 0 - 1 { return 21 } 223 224 // cached: restore the TEST budget (the DEFAULT is now 0 = stream-only; restoring it here 225 // would refuse the fill and break the tooth for a non-cache reason) 226 nx_lw_set_cache_budget(1073741824) 227 let Wcache: *NxF32LazyWeight = nx_f32_lazy_weight_new_q4k(BB, 0, LB_K, LB_N) 228 l_poison(BCc, LB_N) 229 let tf0: i64 = sys_now_us() 230 let vf: nx_int = nx_f32_lazy_matmul(BA, Wcache, BCc, 1, LB_K, LB_N) 231 let us_first: i64 = sys_now_us() - tf0 232 if vf != NX_LW_OK { return 22 } 233 if Wcache.pk_state != 1 { return 22 } 234 let t1: i64 = sys_now_us() 235 var r1: i64 = 0 236 while r1 < LB_REPS { 237 let vc: nx_int = nx_f32_lazy_matmul(BA, Wcache, BCc, 1, LB_K, LB_N) 238 if vc != NX_LW_OK { return 23 } 239 r1 = r1 + 1 240 } 241 let us_cached: i64 = (sys_now_us() - t1) / LB_REPS 242 243 var us_a: i64 = us_stream 244 if us_a < 1 { us_a = 1 } 245 var us_c: i64 = us_cached 246 if us_c < 1 { us_c = 1 } 247 let macs: i64 = LB_K * LB_N 248 fmt_puts("stream_us="); fmt_putn(us_a); fmt_puts(" mflops="); fmt_putn(2 * macs / us_a); l_nl() 249 fmt_puts("cache_fill_us="); fmt_putn(us_first); l_nl() 250 fmt_puts("cached_us="); fmt_putn(us_c); fmt_puts(" mflops="); fmt_putn(2 * macs / us_c); l_nl() 251 let sx100: i64 = us_a * 100 / us_c 252 fmt_puts("cached_vs_stream_x100="); fmt_putn(sx100); l_nl() 253 254 // 2026-08-01: the speed FLOOR is demoted to a PRINTED RECORD, not a tooth. The budget owner 255 // measured that streaming quantized weights beats the cache at decode (hence default=0): the 256 // cache reads 4 B/value while fused streaming reads the 0.56 B/value Q4_K bytes, so at the 257 // memory-bound m=1 shape the cache is no longer presumed faster. A PERF GATE IS NOT A 258 // CORRECTNESS GATE -- this gate's load-bearing claim is tooth 8's bit-equality; speed claims 259 // live in nx_q4k_fused_vs_x4_gate and the budget owner's re-measure. 260 fmt_puts("LWC 7 speedup_x100="); fmt_putn(sx100) 261 fmt_puts(" (record only; floor retired with cache-default-0)"); l_nl() 262 pass = pass + 1 263 264 let ok8: i64 = l_same(BCc, BCs, LB_N) 265 if ok8 != 1 { 266 fmt_puts("LWC 8 BIG-EXACT FAIL"); l_nl() 267 return 25 268 } 269 fmt_puts("LWC 8 BIG-EXACT OK"); l_nl() 270 pass = pass + 1 271 272 fmt_puts("LW_CACHE_GATE "); fmt_putn(pass); fmt_puts("/8 inner"); l_nl() 273 return 0 274} 275 276// D001 migration 2026-08-01 (hand-done; dry_apply cannot see this shape). lwc_run's early returns 277// carry DISTINCT ordered codes (11..16 for teeth 1-6, 21-23 bench infra + retired 24 for tooth 7, 278// 25 for tooth 8), so each tooth's true state is EXACTLY derivable from the rc: reaching code N 279// proves every earlier tooth passed. A tooth that never executed reports FAIL, never PASS. 280func main() -> i64 { 281 let ctr: *i64 = gv_ctr() 282 gv_head("nx_lw_cache_gate -- lazy-weight cache transparency: cached==streamed, budget honesty, Q24 domain" as *u8) 283 let rc: i64 = lwc_run() 284 285 var ok: i64 = 0 286 if rc != 11 { ok = 1 } 287 gv_check("T1 scalar oracle runs" as *u8, ok, ctr) 288 ok = 0 289 if rc == 0 { ok = 1 } 290 if rc > 12 { ok = 1 } 291 gv_check("T2 first dispatch fills the Q24 cache + bit-matches the oracle + exact byte accounting" as *u8, ok, ctr) 292 ok = 0 293 if rc == 0 { ok = 1 } 294 if rc > 13 { ok = 1 } 295 gv_check("T3 cache reuse with fresh activations bit-matches" as *u8, ok, ctr) 296 ok = 0 297 if rc == 0 { ok = 1 } 298 if rc > 14 { ok = 1 } 299 gv_check("T4 m=1 decode shape bit-matches" as *u8, ok, ctr) 300 ok = 0 301 if rc == 0 { ok = 1 } 302 if rc > 15 { ok = 1 } 303 gv_check("T5 budget refusal falls back to streaming, still bit-correct" as *u8, ok, ctr) 304 ok = 0 305 if rc == 0 { ok = 1 } 306 if rc > 16 { ok = 1 } 307 gv_check("T6 stale-shape guard surfaces ERR_INNER" as *u8, ok, ctr) 308 ok = 0 309 if rc == 0 { ok = 1 } 310 if rc > 24 { ok = 1 } 311 gv_check("T7 decode bench runs both lanes (speed = printed record, floor retired)" as *u8, ok, ctr) 312 ok = 0 313 if rc == 0 { ok = 1 } 314 gv_check("T8 BIG-EXACT: cached and streamed bit-identical on the big shape" as *u8, ok, ctr) 315 316 // NO sys_exit HERE: this gate holds a LIVE THREAD POOL, and a single-thread exit leaves the 317 // workers as the process -- both "wedged" runs were exactly this (verdict printed, process 318 // immortal, timeout 124). The KAT pattern's sys_exit is only safe in a threadless organ. 319 // Plain return = the pre-migration idiom; the runtime epilogue ends the whole process. 320 return gv_verdict("LW-CACHE-GATE" as *u8, ctr, "cache is a pure optimisation: one numeric domain on both sides" as *u8) 321}