code wiki / (root) / nx_reader_squad_f32_gate.nx

nx_reader_squad_f32_gate.nx source

↩ module page · 708 lines · 33570 B

1// nx_reader_squad_f32_gate.nx -- R3e of the NEURAL PASSAGE READER arc: TRAIN-ON-F32 (quantize-after comes 2// next). The Q16 lane closed honestly: 6 configurations all entered the uniform-collapse absorbing state at 3// E=24 (see nx_reader_squad_gate). f32 has no quantization floor and no bit-identical-states trap, so the 4// SAME architecture + data + recipe should train. This gate = the Q16 gate ported to the ta_* f32 tensor 5// autograd (transformer ops added 2026-07-09, identities verbatim from the GREEN nfa_* lib). 6// T1 reader held-out span-F1 > question-blind ablation + 100 (liar-kill) 7// T2 reader held-out exact-start > 60 permille (chance ~11) 8// T3 train loss falls > 40% (real learning, no collapse) 9// T4 deterministic re-eval 10// Consumes: reader_rows.bin ('dt'), semppmi_v1.bin (vocab), embed_v1.bin (SGNS Q10 -> f32 RAW magnitude). 11// expect_exit: 0 license_tier: ORIGINAL Sovereign: nx_autograd_tensor (f32) + nx_syscalls. 12import "nx_autograd_tensor.nx" 13import "nx_thread_pool.nx" // RF_PAR: data-parallel batch training across the 16-worker pool 14import "nx_hw.nx" 15import "nx_syscalls.nx" 16 17func rf_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 18func rf_pn(v: i64) -> i64 { let b: *u8=sys_mmap(28); var x: i64=v; if x<0{b[0]=45;sys_write(1,b,1);x=0-x} if x==0{b[0]=48;sys_write(1,b,1);return 0} var d: i64=0; var y: i64=x; while y>0{d=d+1;y=y/10} var i: i64=d-1; y=x; while i>=0{b[i]=(48+(y%10)) as u8;y=y/10;i=i-1} sys_write(1,b,d); return 0 } 19func rf_ck(name: *u8, c: i64) -> i64 { if c==1 { rf_puts(" PASS " as *u8) } else { rf_puts(" FAIL " as *u8) } rf_puts(name); rf_puts("\n" as *u8); return c } 20 21const RF_E: i64 = 24 22const RF_F: i64 = 48 23const RF_MAXT: i64 = 96 24const RF_MAXQ: i64 = 20 25const RF_MAXG: i64 = 8 26// RF_XL flips the whole gate between the small (998-row reader_rows.bin) and the XL (4771-row 27// reader_rows_xl.bin) datasets -- ONE flag, no duplication. RF_NROWS sizes the row arena for either. 28const RF_XL: i64 = 1 29// RF_PAR: run the batch of 8 examples DATA-PARALLEL on the thread pool (per-example private arenas; grads 30// reduced in mb-order => BIT-IDENTICAL to serial => same loss curve, verified vs the serial 8353 reference). 31// Proven correct in nx_ta_parallel_grad_gate. ~5x faster to the verdict on the soft-float bottleneck. 32const RF_PAR: i64 = 1 33const RF_BATCH: i64 = 8 34// RF_CAUSAL: attention masking. 0 = BIDIRECTIONAL (BERT-style), 1 = causal (autoregressive, from the nano-LM). 35// THEORY TESTED + REFUTED (2026-07-10): I hypothesized causal masking was the bug behind the +9-over-ablation 36// gap. Retrained bidirectional (RF_CAUSAL=0): F1=79 vs causal F1=81 -- a WASH (noise-level, slightly WORSE). 37// => masking is NOT the bug; at E=24/1-layer/1-head with static hash embeddings, attention can't extract much 38// question signal regardless of masking. The gap is a CAPACITY/PARADIGM wall, not a wiring error. Kept =1 39// (the marginally-better measured baseline). Real fix = pretrained model (sovereign Qwen), not from-scratch tweaks. 40const RF_CAUSAL: i64 = 1 41const RF_NROWS: i64 = 4800 42const RF_MAXV: i64 = 16384 43const RF_MAPN: i64 = 32768 44const FOFF_EMB: i64 = 0 45const FOFF_WQ: i64 = 393216 46const FOFF_WK: i64 = 393792 47const FOFF_WV: i64 = 394368 48const FOFF_WO: i64 = 394944 49const FOFF_WG: i64 = 395520 50const FOFF_WU: i64 = 396672 51const FOFF_WD: i64 = 397824 52const FOFF_US: i64 = 398976 53const FOFF_UE: i64 = 399000 54const RF_NP: i64 = 399024 55 56// dataset path helpers -- RF_XL selects small vs XL; used by main + the checkpoint fns (no arg-threading). 57func rf_rows_path() -> *u8 { if RF_XL == 1 { return "knowledge/index/reader_rows_xl.bin" as *u8 } return "knowledge/index/reader_rows.bin" as *u8 } 58func rf_ck_path() -> *u8 { if RF_XL == 1 { return "knowledge/index/rsqf32xl_ckpt.bin" as *u8 } return "knowledge/index/rsqf32_ckpt.bin" as *u8 } 59func rf_ck_part_path() -> *u8 { if RF_XL == 1 { return "knowledge/index/rsqf32xl_ckpt.bin.part" as *u8 } return "knowledge/index/rsqf32_ckpt.bin.part" as *u8 } 60func rf_persist_path() -> *u8 { if RF_XL == 1 { return "knowledge/index/reader_neural_f32xl.bin" as *u8 } return "knowledge/index/reader_neural_f32.bin" as *u8 } 61 62func rf_ehash(buf: *u8, off: i64, len: i64) -> i64 { 63 var h1: i64 = 5381 64 var h2: i64 = 77245 65 var i: i64 = 0 66 while i < len { let c: i64 = buf[off+i] as i64; h1 = (h1*33 + c) % 1073741789; h2 = (h2*131 + c) % 1073741783; i = i + 1 } 67 return h1 * 1073741783 + h2 68} 69func rf_bsearch(a: *i64, n: i64, v: i64) -> i64 { 70 var lo: i64 = 0 71 var hi: i64 = n - 1 72 while lo <= hi { let mid: i64 = (lo+hi)/2; if a[mid] == v { return mid } if a[mid] < v { lo = mid+1 } else { hi = mid-1 } } 73 return 0-1 74} 75func rf_lc(c: i64) -> i64 { if c >= 65 { if c <= 90 { return c + 32 } } return c } 76func rf_isal(c: i64) -> i64 { if c >= 97 { if c <= 122 { return 1 } } if c >= 48 { if c <= 57 { return 1 } } return 0 } 77func rf_tok(buf: *u8, n: i64, hout: *i64, cap: i64) -> i64 { 78 let wb: *u8 = sys_mmap(64) 79 var nt: i64 = 0 80 var i: i64 = 0 81 while i < n { 82 let c: i64 = rf_lc(buf[i] as i64) 83 if rf_isal(c) == 1 { 84 var wl: i64 = 0 85 var j: i64 = i 86 var live: i64 = 1 87 while live == 1 { 88 if j >= n { live = 0 } else { 89 let cj: i64 = rf_lc(buf[j] as i64) 90 if rf_isal(cj) == 0 { live = 0 } else { if wl < 48 { wb[wl] = cj as u8; wl = wl + 1 } j = j + 1 } 91 } 92 } 93 if nt < cap { hout[nt] = rf_ehash(wb, 0, wl); nt = nt + 1 } 94 i = j 95 } else { i = i + 1 } 96 } 97 return nt 98} 99func rf_vid(map: *i64, vhash: *i64, vst: *i64, h: i64) -> i64 { 100 var slot: i64 = h & (RF_MAPN - 1) 101 if slot < 0 { slot = 0 - slot } 102 var probe: i64 = 0 103 while probe < RF_MAPN { 104 let e: i64 = map[slot] 105 if e == 0 { 106 if vst[0] >= RF_MAXV - 1 { return 1 } 107 vst[0] = vst[0] + 1 108 let id: i64 = vst[0] 109 vhash[id] = h 110 map[slot] = id 111 return id 112 } 113 if vhash[e] == h { return e } 114 slot = (slot + 1) & (RF_MAPN - 1) 115 probe = probe + 1 116 } 117 return 1 118} 119 120// forward on the ta_ tape (f32). out[0]=loss node, out[1]=Ls, out[2]=Le, out[3]=Xg leaf, out[4..12]=leaves. 121// rtab = precomputed RoPE cos/sin table (nx_f32_sin/cos mmap PER CALL -> table-driven or OOM). 122func rf_fwd(tape: *i64, vals: *i64, st: *i64, W: *i64, Xg: *i64, tgts: *i64, tgte: *i64, T: i64, useattn: i64, out: *i64, rtab: *i64) -> i64 { 123 st[0] = 0 124 st[1] = 0 125 let scale: i64 = nx_f32_div(TA_F32_ONE, nx_f32_sqrt(nx_i32_to_f32(RF_E))) 126 let nXg: i64 = ta_leaf(tape, vals, st, T, RF_E, Xg, 0) 127 let nWq: i64 = ta_leaf(tape, vals, st, RF_E, RF_E, W, FOFF_WQ) 128 let nWk: i64 = ta_leaf(tape, vals, st, RF_E, RF_E, W, FOFF_WK) 129 let nWv: i64 = ta_leaf(tape, vals, st, RF_E, RF_E, W, FOFF_WV) 130 let nWo: i64 = ta_leaf(tape, vals, st, RF_E, RF_E, W, FOFF_WO) 131 let nWg: i64 = ta_leaf(tape, vals, st, RF_E, RF_F, W, FOFF_WG) 132 let nWu: i64 = ta_leaf(tape, vals, st, RF_E, RF_F, W, FOFF_WU) 133 let nWd: i64 = ta_leaf(tape, vals, st, RF_F, RF_E, W, FOFF_WD) 134 let nUs: i64 = ta_leaf(tape, vals, st, 1, RF_E, W, FOFF_US) 135 let nUe: i64 = ta_leaf(tape, vals, st, 1, RF_E, W, FOFF_UE) 136 var nH: i64 = nXg 137 if useattn == 1 { 138 let nXn: i64 = ta_rmsnorm_rows(tape, vals, st, nXg) 139 let nQ: i64 = ta_matmul(tape, vals, st, nXn, nWq) 140 let nK: i64 = ta_matmul(tape, vals, st, nXn, nWk) 141 let nV: i64 = ta_matmul(tape, vals, st, nXn, nWv) 142 let nQr: i64 = ta_rope_tab(tape, vals, st, nQ, rtab) 143 let nKr: i64 = ta_rope_tab(tape, vals, st, nK, rtab) 144 let nS: i64 = ta_matmul_nt(tape, vals, st, nQr, nKr) 145 let nSs: i64 = ta_cmul(tape, vals, st, nS, scale) 146 let nA: i64 = ta_softmax_rows(tape, vals, st, nSs, RF_CAUSAL) // RF_CAUSAL=0 => BIDIRECTIONAL reader 147 let nO: i64 = ta_matmul(tape, vals, st, nA, nV) 148 let nOp: i64 = ta_matmul(tape, vals, st, nO, nWo) 149 nH = ta_vadd(tape, vals, st, nXg, nOp) 150 } 151 let nHn: i64 = ta_rmsnorm_rows(tape, vals, st, nH) 152 let nG: i64 = ta_matmul(tape, vals, st, nHn, nWg) 153 let nU2: i64 = ta_matmul(tape, vals, st, nHn, nWu) 154 let nSg: i64 = ta_silu(tape, vals, st, nG) 155 let nHs: i64 = ta_hadamard(tape, vals, st, nSg, nU2) 156 let nD: i64 = ta_matmul(tape, vals, st, nHs, nWd) 157 let nY: i64 = ta_vadd(tape, vals, st, nH, nD) 158 let nYn: i64 = ta_rmsnorm_rows(tape, vals, st, nY) 159 let nLs: i64 = ta_matmul_nt(tape, vals, st, nUs, nYn) 160 let nLe: i64 = ta_matmul_nt(tape, vals, st, nUe, nYn) 161 let nCs: i64 = ta_softce_rows(tape, vals, st, nLs, tgts) 162 let nCe: i64 = ta_softce_rows(tape, vals, st, nLe, tgte) 163 let nRoot: i64 = ta_vadd(tape, vals, st, nCs, nCe) 164 out[0] = nRoot 165 out[1] = nLs 166 out[2] = nLe 167 out[3] = nXg 168 out[4] = nWq 169 out[5] = nWk 170 out[6] = nWv 171 out[7] = nWo 172 out[8] = nWg 173 out[9] = nWu 174 out[10] = nWd 175 out[11] = nUs 176 out[12] = nUe 177 return 0 178} 179 180// accumulate grads into flat G (f32 adds). Dense weights by layout; embedding rows scattered by token id. 181func rf_grab(tape: *i64, grads: *i64, out: *i64, G: *i64, ids: *i64, T: i64) -> i64 { 182 let nXg: i64 = out[3] 183 let gx: i64 = tape[7*nXg+6] 184 var t: i64 = 0 185 while t < T { 186 let id: i64 = ids[t] 187 var e: i64 = 0 188 while e < RF_E { G[FOFF_EMB + id*RF_E + e] = nx_f32_add(G[FOFF_EMB + id*RF_E + e], grads[gx + t*RF_E + e]); e = e + 1 } 189 t = t + 1 190 } 191 var k: i64 = 0 192 while k < 9 { 193 var sz: i64 = 576 194 var of: i64 = 0 195 if k == 0 { of = FOFF_WQ } 196 if k == 1 { of = FOFF_WK } 197 if k == 2 { of = FOFF_WV } 198 if k == 3 { of = FOFF_WO } 199 if k == 4 { sz = 1152; of = FOFF_WG } 200 if k == 5 { sz = 1152; of = FOFF_WU } 201 if k == 6 { sz = 1152; of = FOFF_WD } 202 if k == 7 { sz = 24; of = FOFF_US } 203 if k == 8 { sz = 24; of = FOFF_UE } 204 let nid: i64 = out[4+k] 205 let goff: i64 = tape[7*nid+6] 206 var i: i64 = 0 207 while i < sz { G[of+i] = nx_f32_add(G[of+i], grads[goff+i]); i = i + 1 } 208 k = k + 1 209 } 210 return 0 211} 212 213// ---- data-parallel batch training (RF_PAR): one example per pool worker, private arenas ---- 214struct RfCtx { 215 w_ptr: i64, 216 ids_ptr: i64, 217 tt: i64, 218 tape_ptr: i64, 219 vals_ptr: i64, 220 grads_ptr: i64, 221 st_ptr: i64, 222 xg_ptr: i64, 223 out_ptr: i64, 224 ge_ptr: i64, 225 rtab_ptr: i64, 226 useattn: i64, 227 tg_ptr: i64, 228 te_ptr: i64, 229 loss_ptr: i64, 230} 231const RF_CTX_BYTES: i64 = 120 232 233// pool worker: gather this example's embeddings, forward, backward, grab grads into its PRIVATE Ge, store loss. 234// Reads W + rtab (shared, read-only) and writes only its private arenas -> thread-safe (proven pattern). 235func rf_par_task(ctx_i: i64) -> i64 { 236 let c: *RfCtx = ctx_i as *RfCtx 237 let W: *i64 = c.w_ptr as *i64 238 let ids: *i64 = c.ids_ptr as *i64 239 let T: i64 = c.tt 240 let tape: *i64 = c.tape_ptr as *i64 241 let vals: *i64 = c.vals_ptr as *i64 242 let grads: *i64 = c.grads_ptr as *i64 243 let st: *i64 = c.st_ptr as *i64 244 let Xg: *i64 = c.xg_ptr as *i64 245 let out: *i64 = c.out_ptr as *i64 246 let Ge: *i64 = c.ge_ptr as *i64 247 let rtab: *i64 = c.rtab_ptr as *i64 248 let tgts: *i64 = c.tg_ptr as *i64 249 let tgte: *i64 = c.te_ptr as *i64 250 let loss: *i64 = c.loss_ptr as *i64 251 var t: i64 = 0 252 while t < T { var e: i64 = 0; while e < RF_E { Xg[t*RF_E+e] = W[FOFF_EMB + ids[t]*RF_E + e]; e = e + 1 } t = t + 1 } 253 rf_fwd(tape, vals, st, W, Xg, tgts, tgte, T, c.useattn, out, rtab) 254 loss[0] = ta_val(tape, vals, out[0], 0) 255 ta_backward(tape, vals, grads, st[0], out[0]) 256 var z: i64 = 0 257 while z < RF_NP { Ge[z] = TA_F32_ZERO; z = z + 1 } 258 rf_grab(tape, grads, out, Ge, ids, T) 259 return 0 260} 261 262func rf_init(W: *i64) -> i64 { 263 var i: i64 = 0 264 while i < 576 { W[FOFF_WQ+i] = ta_constf((((i*13)%9)-4), 32); W[FOFF_WK+i] = ta_constf((((i*17)%9)-4), 32); W[FOFF_WV+i] = ta_constf((((i*19)%9)-4), 32); W[FOFF_WO+i] = ta_constf((((i*23)%9)-4), 32); i = i + 1 } 265 i = 0 266 while i < 1152 { W[FOFF_WG+i] = ta_constf((((i*29)%9)-4), 40); W[FOFF_WU+i] = ta_constf((((i*31)%9)-4), 40); W[FOFF_WD+i] = ta_constf((((i*37)%9)-4), 40); i = i + 1 } 267 i = 0 268 while i < 24 { W[FOFF_US+i] = ta_constf((((i*5+1)%7)-3), 8); W[FOFF_UE+i] = ta_constf((((i*11+2)%7)-3), 8); i = i + 1 } 269 return 0 270} 271 272func rf_span_f1(ids: *i64, a: i64, b: i64, gs: i64, ge: i64) -> i64 { 273 let pl: i64 = b - a + 1 274 let gl: i64 = ge - gs + 1 275 if pl <= 0 { return 0 } 276 if gl <= 0 { return 0 } 277 var common: i64 = 0 278 let used: *i64 = sys_mmap(RF_MAXG*8) as *i64 279 var u: i64 = 0 280 while u < gl { used[u] = 0; u = u + 1 } 281 var p: i64 = a 282 while p <= b { 283 var q2: i64 = 0 284 var got: i64 = 0 285 while q2 < gl { 286 if got == 0 { if used[q2] == 0 { if ids[gs+q2] == ids[p] { used[q2] = 1; common = common + 1; got = 1 } } } 287 q2 = q2 + 1 288 } 289 p = p + 1 290 } 291 if common == 0 { return 0 } 292 return (2*common*1000)/(pl+gl) 293} 294 295func rf_eval(tape: *i64, vals: *i64, st: *i64, W: *i64, dat: *i64, meta: *i64, r0: i64, r1: i64, useattn: i64, res: *i64, rtab: *i64) -> i64 { 296 let out: *i64 = sys_mmap(16*8) as *i64 297 let Xg: *i64 = sys_mmap(RF_MAXT*RF_E*8) as *i64 298 let tgts: *i64 = sys_mmap(8) as *i64 299 let tgte: *i64 = sys_mmap(8) as *i64 300 var f1sum: i64 = 0 301 var exact: i64 = 0 302 var n: i64 = 0 303 var r: i64 = r0 304 while r < r1 { 305 let T: i64 = meta[r*4+0] 306 let qn: i64 = meta[r*4+1] 307 let gs: i64 = meta[r*4+2] 308 let ge: i64 = meta[r*4+3] 309 let ids: *i64 = (dat as i64 + r*RF_MAXT*8) as *i64 310 var t: i64 = 0 311 while t < T { var e: i64 = 0; while e < RF_E { Xg[t*RF_E+e] = W[FOFF_EMB + ids[t]*RF_E + e]; e = e + 1 } t = t + 1 } 312 tgts[0] = gs 313 tgte[0] = ge 314 rf_fwd(tape, vals, st, W, Xg, tgts, tgte, T, useattn, out, rtab) 315 let nLs: i64 = out[1] 316 let nLe: i64 = out[2] 317 var s: i64 = qn + 1 318 var bv: i64 = ta_val(tape, vals, nLs, qn+1) 319 var j: i64 = qn + 2 320 while j < T { let v: i64 = ta_val(tape, vals, nLs, j); if nx_f32_gt(v, bv) == 1 { bv = v; s = j } j = j + 1 } 321 var en: i64 = s 322 var ev: i64 = ta_val(tape, vals, nLe, s) 323 var lim: i64 = s + RF_MAXG 324 if lim > T { lim = T } 325 j = s + 1 326 while j < lim { let v2: i64 = ta_val(tape, vals, nLe, j); if nx_f32_gt(v2, ev) == 1 { ev = v2; en = j } j = j + 1 } 327 f1sum = f1sum + rf_span_f1(ids, s, en, gs, ge) 328 if s == gs { exact = exact + 1 } 329 n = n + 1 330 r = r + 1 331 } 332 if n == 0 { res[0] = 0; res[1] = 0; return 0 } 333 res[0] = f1sum / n 334 res[1] = exact * 1000 / n 335 return 0 336} 337 338// ---- CRASH-TOLERANT CHECKPOINTING (the box gets VM-restarted by sibling sessions; per-epoch checkpoints make 339// any interruption cost <=1 epoch and progress accumulate monotonically). Layout (i64 cells): 340// ck[0]=magic (20262), ck[1]=reader epochs done, ck[2]=ablation epochs done, ck[3]=nw, 341// ck[4]=reader FIRST-epoch loss milli, ck[5]=reader LAST-epoch loss milli (T3 survives resume), 342// ck[6..6+NP) = W (reader), ck[6+NP..6+2NP) = W2 (ablation). W/W2 point INTO ck -> flush = one write. ---- 343const RF_CKMAGIC: i64 = 20262 344const RF_CKCELLS: i64 = 6 + RF_NP + RF_NP 345 346func rf_ck_flush(ck: *i64) -> i64 { 347 // ATOMIC checkpoint: write .part, then rename over the live file. A VM kill mid-write (the box gets 348 // sibling-restarted ~15min) must never leave a TORN checkpoint -- a torn one resumes into garbage weights 349 // and trains on silently. rename on the same fs is atomic => the live ckpt is always old-complete or 350 // new-complete, never partial. 351 let fd: i64 = sys_openat_wr(rf_ck_part_path(), 0x1a4) 352 if fd < 0 { return 0 } 353 let nb: i64 = RF_CKCELLS * 8 354 var w: i64 = 0 355 while w < nb { let x: i64 = sys_write(fd, (ck as i64 + w) as *u8, nb - w); if x <= 0 { w = nb } else { w = w + x } } 356 sys_close(fd) 357 if w < nb { return 0 } 358 sys_renameat(rf_ck_part_path(), rf_ck_path()) 359 return 1 360} 361 362func rf_ck_load(ck: *i64, nw: i64) -> i64 { 363 let fd: i64 = sys_openat_rd(rf_ck_path()) 364 if fd < 0 { return 0 } 365 let nb: i64 = RF_CKCELLS * 8 366 var got: i64 = 0 367 var r: i64 = 1 368 while r > 0 { if got >= nb { r = 0 } else { r = sys_read(fd, (ck as i64 + got) as *u8, nb - got); if r > 0 { got = got + r } } } 369 sys_close(fd) 370 if got < nb { return 0 } 371 if ck[0] != RF_CKMAGIC { return 0 } 372 if ck[3] != nw { return 0 } 373 return 1 374} 375 376// train from start-epoch ep0 (checkpoint-resume); saves the checkpoint after EVERY epoch (ckslot 1=reader, 377// 2=ablation). res0[0]=final-epoch mean loss milli, res0[1]=first-SEEN-epoch mean (for the fall test). 378func rf_train(tape: *i64, vals: *i64, grads: *i64, st: *i64, W: *i64, dat: *i64, meta: *i64, ntrain: i64, useattn: i64, EP: i64, res0: *i64, ck: *i64, ckslot: i64, ep0: i64, rtab: *i64) -> i64 { 379 let out: *i64 = sys_mmap(16*8) as *i64 380 let Xg: *i64 = sys_mmap(RF_MAXT*RF_E*8) as *i64 381 let tgts: *i64 = sys_mmap(8) as *i64 382 let tgte: *i64 = sys_mmap(8) as *i64 383 let G: *i64 = sys_mmap(RF_NP*8) as *i64 384 let lr0: i64 = ta_constf(1, 32) // 0.03125 = R3a's proven rate 385 let clip: i64 = nx_i32_to_f32(4) 386 let nclip: i64 = nx_f32_neg(clip) 387 let inv8: i64 = ta_constf(1, 8) 388 // RF_PAR: pool + RF_BATCH private per-example arena sets (allocated ONCE, reused across epochs/batches) 389 var pool: *NxThreadPool = 0 as *NxThreadPool 390 let ptapes: *i64 = sys_mmap(RF_BATCH*4096*7*8) as *i64 391 let pvals: *i64 = sys_mmap(RF_BATCH*262144*8) as *i64 392 let pgrads: *i64 = sys_mmap(RF_BATCH*262144*8) as *i64 393 let psts: *i64 = sys_mmap(RF_BATCH*2*8) as *i64 394 let pxgs: *i64 = sys_mmap(RF_BATCH*RF_MAXT*RF_E*8) as *i64 395 let pouts: *i64 = sys_mmap(RF_BATCH*16*8) as *i64 396 let pges: *i64 = sys_mmap(RF_BATCH*RF_NP*8) as *i64 397 let plosses: *i64 = sys_mmap(RF_BATCH*8) as *i64 398 let ptg: *i64 = sys_mmap(RF_BATCH*2*8) as *i64 399 let pctxs: *u8 = sys_mmap(RF_BATCH*RF_CTX_BYTES) 400 if RF_PAR == 1 { pool = nx_pool_new(0, 0) } 401 var first: i64 = 1 402 var ep: i64 = ep0 403 while ep < EP { 404 var lsum: i64 = TA_F32_ZERO 405 var nb: i64 = 0 406 var r: i64 = 0 407 while r + 8 <= ntrain { 408 var z: i64 = 0 409 while z < RF_NP { G[z] = TA_F32_ZERO; z = z + 1 } 410 if RF_PAR == 1 { 411 // ---- PARALLEL: submit RF_BATCH examples to the pool, each on private arenas ---- 412 let db: i64 = nx_pool_n_completed(pool) 413 var mb: i64 = 0 414 while mb < RF_BATCH { 415 let rr: i64 = r + mb 416 ptg[mb*2] = meta[rr*4+2] 417 ptg[mb*2+1] = meta[rr*4+3] 418 let cx: *RfCtx = ((pctxs as i64) + mb*RF_CTX_BYTES) as *RfCtx 419 cx.w_ptr = W as i64 420 cx.ids_ptr = (dat as i64 + rr*RF_MAXT*8) 421 cx.tt = meta[rr*4+0] 422 cx.tape_ptr = (ptapes as i64 + mb*4096*7*8) 423 cx.vals_ptr = (pvals as i64 + mb*262144*8) 424 cx.grads_ptr = (pgrads as i64 + mb*262144*8) 425 cx.st_ptr = (psts as i64 + mb*2*8) 426 cx.xg_ptr = (pxgs as i64 + mb*RF_MAXT*RF_E*8) 427 cx.out_ptr = (pouts as i64 + mb*16*8) 428 cx.ge_ptr = (pges as i64 + mb*RF_NP*8) 429 cx.rtab_ptr = rtab as i64 430 cx.useattn = useattn 431 cx.tg_ptr = (ptg as i64 + mb*2*8) 432 cx.te_ptr = (ptg as i64 + (mb*2+1)*8) 433 cx.loss_ptr = (plosses as i64 + mb*8) 434 nx_pool_submit(pool, rf_par_task, cx as i64) 435 mb = mb + 1 436 } 437 nx_pool_wait(pool, db + RF_BATCH) 438 // reduce per-example grads (mb order = bit-identical to serial) + sum losses 439 mb = 0 440 while mb < RF_BATCH { 441 let Ge: *i64 = (pges as i64 + mb*RF_NP*8) as *i64 442 var zz: i64 = 0 443 while zz < RF_NP { G[zz] = nx_f32_add(G[zz], Ge[zz]); zz = zz + 1 } 444 lsum = nx_f32_add(lsum, plosses[mb]) 445 mb = mb + 1 446 } 447 } else { 448 var mb: i64 = 0 449 while mb < RF_BATCH { 450 let rr: i64 = r + mb 451 let T: i64 = meta[rr*4+0] 452 let gs: i64 = meta[rr*4+2] 453 let ge: i64 = meta[rr*4+3] 454 let ids: *i64 = (dat as i64 + rr*RF_MAXT*8) as *i64 455 var t: i64 = 0 456 while t < T { var e: i64 = 0; while e < RF_E { Xg[t*RF_E+e] = W[FOFF_EMB + ids[t]*RF_E + e]; e = e + 1 } t = t + 1 } 457 tgts[0] = gs 458 tgte[0] = ge 459 rf_fwd(tape, vals, st, W, Xg, tgts, tgte, T, useattn, out, rtab) 460 let nRoot: i64 = out[0] 461 lsum = nx_f32_add(lsum, ta_val(tape, vals, nRoot, 0)) 462 ta_backward(tape, vals, grads, st[0], nRoot) 463 rf_grab(tape, grads, out, G, ids, T) 464 mb = mb + 1 465 } 466 } 467 // decay: small=24/40 (48-ep schedule); XL=8/12 (16-ep, 7x more data/epoch converges faster) 468 var d1: i64 = 24 469 var d2: i64 = 40 470 if RF_XL == 1 { d1 = 8; d2 = 12 } 471 var elr: i64 = lr0 472 if ep >= d1 { elr = nx_f32_mul(lr0, ta_constf(1, 2)) } 473 if ep >= d2 { elr = nx_f32_mul(lr0, ta_constf(1, 4)) } 474 var w: i64 = 0 475 while w < RF_NP { 476 var gv: i64 = nx_f32_mul(G[w], inv8) 477 if nx_f32_gt(gv, clip) == 1 { gv = clip } 478 if nx_f32_lt(gv, nclip) == 1 { gv = nclip } 479 W[w] = nx_f32_sub(W[w], nx_f32_mul(elr, gv)) 480 w = w + 1 481 } 482 nb = nb + 1 483 r = r + 8 484 } 485 let mean: i64 = nx_f32_div(lsum, nx_i32_to_f32(nb*8)) 486 let mm: i64 = ta_f32_to_milli(mean) 487 if first == 1 { res0[1] = mm; first = 0 } 488 res0[0] = mm 489 rf_puts(" epoch "); rf_pn(ep); rf_puts(" mean_loss_milli="); rf_pn(mm); rf_puts("\n" as *u8) 490 if ckslot == 1 { if ep == 0 { ck[4] = mm } ck[5] = mm } 491 ck[ckslot] = ep + 1 492 rf_ck_flush(ck) 493 ep = ep + 1 494 } 495 return 0 496} 497 498func main() -> i64 { 499 rf_puts("nx_reader_squad_f32_gate (R3e: TRAIN-ON-F32 -- same reader, ta_* tensor autograd; Q16 collapse trap does not exist here)\n" as *u8) 500 var pass: i64 = 0 501 var total: i64 = 0 502 503 let fd: i64 = sys_openat_rd(rf_rows_path()) 504 if fd < 0 { rf_puts("RED -- reader rows file missing (run: nx_qabench dt / dx)\n" as *u8); return 1 } 505 let cap: i64 = 16777216 506 let raw: *u8 = sys_mmap(cap) 507 var got: i64 = 0 508 var rr2: i64 = 1 509 while rr2 > 0 { rr2 = sys_read(fd, (raw as i64 + got) as *u8, cap - got); if rr2 > 0 { got = got + rr2 } } 510 sys_close(fd) 511 if got < 16 { rf_puts("RED -- reader_rows.bin empty\n" as *u8); return 1 } 512 513 let pfd: i64 = sys_openat_rd("knowledge/index/semppmi_v1.bin" as *u8) 514 if pfd < 0 { rf_puts("RED -- semppmi_v1.bin missing\n" as *u8); return 1 } 515 let pcap: i64 = 2097152 516 let pblob: *u8 = sys_mmap(pcap) 517 var pgot: i64 = 0 518 var pr: i64 = 1 519 while pr > 0 { if pgot >= pcap { pr = 0 } else { pr = sys_read(pfd, (pblob as i64 + pgot) as *u8, pcap - pgot); if pr > 0 { pgot = pgot + pr } } } 520 sys_close(pfd) 521 let phi: *i64 = (pblob as i64 + 8) as *i64 522 let nv: i64 = phi[0] 523 if pgot < 32 + nv*8 { rf_puts("RED -- semppmi vh truncated\n" as *u8); return 1 } 524 let vh: *i64 = (pblob as i64 + 32) as *i64 525 let efd: i64 = sys_openat_rd("knowledge/index/embed_v1.bin" as *u8) 526 if efd < 0 { rf_puts("RED -- embed_v1.bin missing\n" as *u8); return 1 } 527 let ecap: i64 = 67108864 528 let eblob: *u8 = sys_mmap(ecap) 529 var egot: i64 = 0 530 var er: i64 = 1 531 while er > 0 { if egot >= ecap { er = 0 } else { er = sys_read(efd, (eblob as i64 + egot) as *u8, ecap - egot); if er > 0 { egot = egot + er } } } 532 sys_close(efd) 533 let ehi: *i64 = (eblob as i64 + 8) as *i64 534 let env: i64 = ehi[0] 535 let edim: i64 = ehi[1] 536 if edim != RF_E { rf_puts("RED -- embed dim mismatch\n" as *u8); return 1 } 537 if env != nv { rf_puts("RED -- embed/vocab nv mismatch\n" as *u8); return 1 } 538 let EQ: *i64 = (eblob as i64 + 24) as *i64 539 rf_puts(" SGNS loaded: vocab nv="); rf_pn(nv); rf_puts(" dim="); rf_pn(edim); rf_puts("\n" as *u8) 540 541 let dat: *i64 = sys_mmap(RF_NROWS*RF_MAXT*8) as *i64 542 let meta: *i64 = sys_mmap(RF_NROWS*4*8) as *i64 543 let qh: *i64 = sys_mmap(64*8) as *i64 544 let ch: *i64 = sys_mmap(4096*8) as *i64 545 let gh: *i64 = sys_mmap(64*8) as *i64 546 let vhash: *i64 = sys_mmap(RF_MAXV*8) as *i64 547 let vmap: *i64 = sys_mmap(RF_MAPN*8) as *i64 548 let vst: *i64 = sys_mmap(8) as *i64 549 vst[0] = 0 550 var nrows: i64 = 0 551 var off: i64 = 8 552 var scanned: i64 = 0 553 while off + 24 < got { 554 if nrows >= RF_NROWS { off = got } else { 555 let hp: *i64 = (raw as i64 + off) as *i64 556 let qlen: i64 = hp[0] 557 if qlen < 0 { off = got } else { if qlen > 4000 { off = got } else { 558 let qp: *u8 = (raw as i64 + off + 8) as *u8 559 let hp2: *i64 = (raw as i64 + off + 8 + qlen) as *i64 560 let clen: i64 = hp2[0] 561 let cp: *u8 = (raw as i64 + off + 16 + qlen) as *u8 562 let hp3: *i64 = (raw as i64 + off + 16 + qlen + clen) as *i64 563 let alen: i64 = hp3[0] 564 let ap: *u8 = (raw as i64 + off + 24 + qlen + clen) as *u8 565 off = off + 24 + qlen + clen + alen 566 scanned = scanned + 1 567 var qn: i64 = rf_tok(qp, qlen, qh, RF_MAXQ) 568 let cn0: i64 = rf_tok(cp, clen, ch, 4096) 569 let gn: i64 = rf_tok(ap, alen, gh, RF_MAXG) 570 var cn: i64 = RF_MAXT - qn - 1 571 if cn > cn0 { cn = cn0 } 572 if qn >= 3 { if gn >= 1 { if cn >= 8 { 573 var gs: i64 = 0-1 574 var c: i64 = 0 575 while c + gn <= cn { 576 if gs < 0 { 577 var m: i64 = 1 578 var k: i64 = 0 579 while k < gn { if ch[c+k] != gh[k] { m = 0; k = gn } else { k = k + 1 } } 580 if m == 1 { gs = c } 581 } 582 c = c + 1 583 } 584 if gs >= 0 { 585 let T: i64 = qn + 1 + cn 586 let ids: *i64 = (dat as i64 + nrows*RF_MAXT*8) as *i64 587 var t: i64 = 0 588 while t < qn { let lid: i64 = rf_vid(vmap, vhash, vst, qh[t]); ids[t] = lid; t = t + 1 } 589 ids[qn] = 0 590 t = 0 591 while t < cn { let lid2: i64 = rf_vid(vmap, vhash, vst, ch[t]); ids[qn+1+t] = lid2; t = t + 1 } 592 meta[nrows*4+0] = T 593 meta[nrows*4+1] = qn 594 meta[nrows*4+2] = qn + 1 + gs 595 meta[nrows*4+3] = qn + 1 + gs + gn - 1 596 nrows = nrows + 1 597 } 598 } } } 599 } } 600 } 601 } 602 let nw: i64 = vst[0] 603 rf_puts(" scanned="); rf_pn(scanned); rf_puts(" usable="); rf_pn(nrows); rf_puts(" vocab nw="); rf_pn(nw); rf_puts("\n" as *u8) 604 if nrows < 200 { rf_puts("RED -- too few usable rows\n" as *u8); return 1 } 605 var ntrain: i64 = (nrows * 4) / 5 606 rf_puts(" train="); rf_pn(ntrain); rf_puts(" held-out="); rf_pn(nrows - ntrain); rf_puts("\n" as *u8) 607 608 // ---- checkpoint buffer: W/W2 live INSIDE it; resume if a valid checkpoint exists ---- 609 let ck: *i64 = sys_mmap(RF_CKCELLS*8) as *i64 610 let W: *i64 = (ck as i64 + 6*8) as *i64 611 let W2: *i64 = (ck as i64 + (6 + RF_NP)*8) as *i64 612 let resumed: i64 = rf_ck_load(ck, nw) 613 if resumed == 1 { 614 rf_puts(" CHECKPOINT RESUMED: reader epochs done="); rf_pn(ck[1]); rf_puts(" ablation done="); rf_pn(ck[2]); rf_puts("\n" as *u8) 615 } else { 616 ck[0] = RF_CKMAGIC 617 ck[1] = 0 618 ck[2] = 0 619 ck[3] = nw 620 ck[4] = 0 621 ck[5] = 0 622 // embeddings: SGNS Q10 -> f32 RAW magnitude (f32 has no absorbing trap; true init) 623 let q10: i64 = nx_i32_to_f32(1024) 624 var hits: i64 = 0 625 var wv: i64 = 1 626 while wv <= nw { 627 let r3: i64 = rf_bsearch(vh, nv, vhash[wv]) 628 if r3 >= 0 { 629 var e2: i64 = 0 630 while e2 < RF_E { W[FOFF_EMB + wv*RF_E + e2] = nx_f32_div(nx_i32_to_f32(EQ[r3*RF_E + e2]), q10); e2 = e2 + 1 } 631 hits = hits + 1 632 } else { 633 var e3: i64 = 0 634 while e3 < RF_E { W[FOFF_EMB + wv*RF_E + e3] = ta_constf((((wv*7+e3*3)%11)-5), 16); e3 = e3 + 1 } 635 } 636 wv = wv + 1 637 } 638 var e4: i64 = 0 639 while e4 < RF_E { W[FOFF_EMB + e4] = ta_constf((((e4*5+2)%9)-4), 12); e4 = e4 + 1 } 640 rf_puts(" SGNS coverage: "); rf_pn(hits); rf_puts("/"); rf_pn(nw); rf_puts("\n" as *u8) 641 rf_init(W) 642 var cw: i64 = 0 643 while cw < RF_NP { W2[cw] = W[cw]; cw = cw + 1 } 644 rf_init(W2) 645 rf_ck_flush(ck) 646 } 647 648 let tape: *i64 = sys_mmap(4096*7*8) as *i64 649 let vals: *i64 = sys_mmap(262144*8) as *i64 650 let grads: *i64 = sys_mmap(262144*8) as *i64 651 let st: *i64 = sys_mmap(2*8) as *i64 652 var EP: i64 = 48 // small: 48-ep (664 rows undertrained at 12). XL: 16-ep (4771 rows, 7x more 653 if RF_XL == 1 { EP = 16 } // examples/epoch -> converges in fewer epochs; checkpoint lets us stop early. 654 // RoPE table: ONE build (sin/cos mmap per call; 96*12*2 calls once = fine, per-element in the loop = OOM) 655 let rtab: *i64 = sys_mmap((2 + 2*RF_MAXT*(RF_E/2))*8) as *i64 656 ta_rope_build_tab(rtab, RF_MAXT, RF_E/2) 657 rf_puts(" RoPE table built ("); rf_pn(RF_MAXT); rf_puts("x"); rf_pn(RF_E/2); rf_puts(")\n" as *u8) 658 659 rf_puts(" training READER (f32, SGNS init, R3a recipe; checkpointed per epoch)...\n" as *u8) 660 let resL: *i64 = sys_mmap(2*8) as *i64 661 resL[1] = 0 662 if ck[1] < EP { rf_train(tape, vals, grads, st, W, dat, meta, ntrain, 1, EP, resL, ck, 1, ck[1], rtab) } 663 let resA: *i64 = sys_mmap(2*8) as *i64 664 rf_eval(tape, vals, st, W, dat, meta, ntrain, nrows, 1, resA, rtab) 665 rf_puts(" READER held-out: span-F1="); rf_pn(resA[0]); rf_puts(" exact-start="); rf_pn(resA[1]); rf_puts(" permille\n" as *u8) 666 667 rf_puts(" training ABLATION (question-blind, same everything; checkpointed)...\n" as *u8) 668 let resL2: *i64 = sys_mmap(2*8) as *i64 669 if ck[2] < EP { rf_train(tape, vals, grads, st, W2, dat, meta, ntrain, 0, EP, resL2, ck, 2, ck[2], rtab) } 670 let resB: *i64 = sys_mmap(2*8) as *i64 671 rf_eval(tape, vals, st, W2, dat, meta, ntrain, nrows, 0, resB, rtab) 672 rf_puts(" ABLATION held-out: span-F1="); rf_pn(resB[0]); rf_puts(" exact-start="); rf_pn(resB[1]); rf_puts(" permille\n" as *u8) 673 674 total = total + 1 675 if resA[0] > resB[0] + 100 { pass = pass + 1; rf_ck("T1 reader beats question-blind ablation by >100 F1 (liar-kill)" as *u8, 1) } else { rf_ck("T1 reader beats question-blind ablation by >100 F1 (liar-kill)" as *u8, 0) } 676 total = total + 1 677 if resA[1] > 60 { pass = pass + 1; rf_ck("T2 reader exact-start > 60 permille" as *u8, 1) } else { rf_ck("T2 reader exact-start > 60 permille" as *u8, 0) } 678 total = total + 1 679 var t3: i64 = 0 680 if ck[4] > 0 { if ck[5]*10 < ck[4]*6 { t3 = 1 } } // first vs last reader-epoch loss FROM THE CHECKPOINT (resume-safe) 681 if t3 == 1 { pass = pass + 1; rf_ck("T3 train loss falls >40% (no collapse)" as *u8, 1) } else { rf_ck("T3 train loss falls >40% (no collapse)" as *u8, 0) } 682 683 let resC: *i64 = sys_mmap(2*8) as *i64 684 rf_eval(tape, vals, st, W, dat, meta, ntrain, nrows, 1, resC, rtab) 685 total = total + 1 686 var t4: i64 = 0 687 if resC[0] == resA[0] { if resC[1] == resA[1] { t4 = 1 } } 688 if t4 == 1 { pass = pass + 1; rf_ck("T4 deterministic re-eval" as *u8, 1) } else { rf_ck("T4 deterministic re-eval" as *u8, 0) } 689 690 let pf: i64 = sys_openat_wr(rf_persist_path(), 0x1a4) 691 if pf >= 0 { 692 let mg: *i64 = sys_mmap(32) as *i64 693 let mgb: *u8 = mg as *u8 694 mgb[0]=78 as u8; mgb[1]=88 as u8; mgb[2]=78 as u8; mgb[3]=82 as u8; mgb[4]=51 as u8; mgb[5]=0 as u8; mgb[6]=0 as u8; mgb[7]=0 as u8 695 mg[1] = nw 696 mg[2] = RF_E 697 mg[3] = RF_F 698 sys_write(pf, mg as *u8, 32) 699 sys_write(pf, W as *u8, RF_NP*8) 700 sys_close(pf) 701 rf_puts(" persisted trained f32 reader -> knowledge/index/reader_neural_f32.bin (NXNR3)\n" as *u8) 702 } 703 704 rf_puts("---- nx_reader_squad_f32_gate: passed "); rf_pn(pass); rf_puts(" / "); rf_pn(total); rf_puts("\n" as *u8) 705 if pass == total { rf_puts("READER R3e GREEN -- the f32-trained attention reader LEARNS + GENERALIZES on real SQuAD where the question-blind reader cannot; quantize-after is next.\n" as *u8); return 0 } 706 rf_puts("RED -- R3e not fully passed (see numbers)\n" as *u8) 707 return 1 708}