code wiki / _hdl_build / nx_nofloat_scale_wide_gate.nx

nx_nofloat_scale_wide_gate.nx source

↩ module page · 147 lines · 9113 B

1// nx_nofloat_scale_wide_gate.nx -- R4 the genuine SCALE test: real WIDTH scale-up. Prior R4 tests stayed at 2// dm=24/32 and ruled out optimizer/depth/batch/FFN -- but WIDTH (features per token) is distinct from depth and 3// is exactly what producing SHARP 4-way-conditional distributions needs. Maximal tractable model: dm=64, 4// ffn=128, the COMPLETE block (attn+FFN), mini-batch averaged grads (lowest noise). Richer 4-cat grammar. 5// floor = avg(ln2,ln4,ln5,ln5)=1324 milli-nats (ppl 3.76); uniform=2773; dm=32 plateaued ~2135 (ppl 8.5). 6// T1 held-out CE << uniform. T2 held-out CE ~= floor (near-OPTIMAL -> WIDTH-scale closes it -> R4 progresses). 7// If T2 fails too, even 2x width is insufficient at tractable compute -> R4-FULL needs massive (GPU-scale) compute. 8// expect_exit: 0 Sovereign: nx_nofloat_autograd + nx_syscalls. (run in background -- longer compute) 9// 10// D001 MIGRATION 2026-08-25: this gate hand-rolled its own verdict -- a local pass/total pair, its own 11// "passed p / t" summary line, and its own verdict=GREEN/RED prints -- so the EXIT CODE carried the verdict 12// only while the author kept the two in step, and a tooth that silently stopped running would have lowered 13// BOTH numbers and still read GREEN. It now inherits nx_gate_verdict: gv_ctr makes declared and executed 14// tooth counts ONE number, and gv_verdict is the single writer of the last line. The two assertions are 15// UNCHANGED -- same expressions, same thresholds, same wording -- only the bookkeeping moved to the base 16// class. The two bars are now NAMED consts instead of bare literals sitting inside the comparisons. 17import "nx_nofloat_autograd.nx" 18import "nx_syscalls.nx" 19import "nx_gate_emit_lib.nx" 20import "nx_gate_verdict.nx" 21const Q16: i64 = 65536 22const UNIFORM_MNAT: i64 = 2773 23const FLOOR_MNAT: i64 = 1324 24// The T1 bar: held-out CE must be at most this fraction (7/10) of the uniform-baseline CE -- the model must 25// have learned a real amount of the language, not merely twitched off uniform. Kept as an exact 26// numerator/denominator pair so the comparison arithmetic is byte-for-byte the one that shipped. 27const T1_UNIFORM_FRAC_NUM: i64 = 7 28const T1_UNIFORM_FRAC_DEN: i64 = 10 29// The T2 bar: how many milli-nats ABOVE the entropy floor of the grammar still counts as near-optimal. 30const T2_NEAR_FLOOR_TOL_MNAT: i64 = 200 31 32 33func dini(a: *i64, n: i64, sd: i64) -> i64 { var i: i64=0; while i<n { a[i]=(((i*7+sd*13+1)%11)-5)*9362; i=i+1 } return 0 } 34func lcg(st: *i64) -> i64 { st[0]=(st[0]*1103515245 + 12345) & 2147483647; return (st[0] >> 15) } 35func make_stream4(S: *i64, tgt: *i64, P: i64, st: *i64) -> i64 { 36 var i: i64=0 37 while i<P { let c: i64=i%4; if c==0 { S[i]=lcg(st)%2 } if c==1 { S[i]=2+lcg(st)%4 } if c==2 { S[i]=6+lcg(st)%5 } if c==3 { S[i]=11+lcg(st)%5 } i=i+1 } 38 i=0; while i<P-1 { tgt[i]=S[i+1]; i=i+1 } tgt[P-1]=S[0] 39 return 0 40} 41func clm_ffn(tape: *i64, vals: *i64, st: *i64, W: *i64, ids: *i64, tgt: *i64, T: i64, dm: i64, ffn: i64, V: i64, scale: i64, lv: *i64) -> i64 { 42 st[0]=0; st[1]=0 43 let nE: i64=nfa_leaf(tape,vals,st,V,dm,W[0] as *i64,0) 44 let nWq: i64=nfa_leaf(tape,vals,st,dm,dm,W[1] as *i64,0) 45 let nWk: i64=nfa_leaf(tape,vals,st,dm,dm,W[2] as *i64,0) 46 let nWv: i64=nfa_leaf(tape,vals,st,dm,dm,W[3] as *i64,0) 47 let nWo: i64=nfa_leaf(tape,vals,st,dm,dm,W[4] as *i64,0) 48 let nW1: i64=nfa_leaf(tape,vals,st,dm,ffn,W[5] as *i64,0) 49 let nW2: i64=nfa_leaf(tape,vals,st,ffn,dm,W[6] as *i64,0) 50 let nWlm: i64=nfa_leaf(tape,vals,st,dm,V,W[7] as *i64,0) 51 let nX: i64=nfa_embed(tape,vals,st,nE,ids,T) 52 let nXn: i64=nfa_rmsnorm_rows(tape,vals,st,nX) 53 let nQ: i64=nfa_matmul(tape,vals,st,nXn,nWq) 54 let nK: i64=nfa_matmul(tape,vals,st,nXn,nWk) 55 let nV: i64=nfa_matmul(tape,vals,st,nXn,nWv) 56 let nQr: i64=nfa_rope(tape,vals,st,nQ) 57 let nKr: i64=nfa_rope(tape,vals,st,nK) 58 let nS: i64=nfa_matmul_nt(tape,vals,st,nQr,nKr) 59 let nSs: i64=nfa_cmul(tape,vals,st,nS,scale) 60 let nA: i64=nfa_softmax_rows(tape,vals,st,nSs,1) 61 let nO: i64=nfa_matmul(tape,vals,st,nA,nV) 62 let nOp: i64=nfa_matmul(tape,vals,st,nO,nWo) 63 let nH: i64=nfa_vadd(tape,vals,st,nX,nOp) 64 let nHn: i64=nfa_rmsnorm_rows(tape,vals,st,nH) 65 let nF1: i64=nfa_matmul(tape,vals,st,nHn,nW1) 66 let nFs: i64=nfa_silu(tape,vals,st,nF1) 67 let nF2: i64=nfa_matmul(tape,vals,st,nFs,nW2) 68 let nH2: i64=nfa_vadd(tape,vals,st,nH,nF2) 69 let nH2n: i64=nfa_rmsnorm_rows(tape,vals,st,nH2) 70 let nLg: i64=nfa_matmul(tape,vals,st,nH2n,nWlm) 71 let nLoss: i64=nfa_softce_rows(tape,vals,st,nLg,tgt) 72 lv[0]=nE; lv[1]=nWq; lv[2]=nWk; lv[3]=nWv; lv[4]=nWo; lv[5]=nW1; lv[6]=nW2; lv[7]=nWlm; lv[8]=nLg 73 return nLoss 74} 75func do_train_batch(tape: *i64, vals: *i64, grads: *i64, st: *i64, W: *i64, WN: *i64, gacc: *i64, S: *i64, tgt: *i64, P: i64, dm: i64, ffn: i64, V: i64, scale: i64, lv: *i64, gb: *i64, outer: i64, B: i64, lr: i64, sdat: *i64) -> i64 { 76 var s: i64=0 77 while s<outer { 78 var i: i64=0 79 while i<8 { let ga: *i64=gacc[i] as *i64; let cn: i64=WN[i]; var c: i64=0; while c<cn { ga[c]=0; c=c+1 } i=i+1 } 80 var b: i64=0 81 while b<B { 82 make_stream4(S,tgt,P,sdat) 83 let nl: i64=clm_ffn(tape,vals,st,W,S,tgt,P-1,dm,ffn,V,scale,lv) 84 nfa_backward(tape,vals,grads,st[0],nl) 85 i=0 86 while i<8 { let ga: *i64=gacc[i] as *i64; let cn: i64=WN[i]; let nd: i64=lv[i]; var c: i64=0; while c<cn { var g: i64=nfa_grad(tape,grads,nd,c); if g>262144{g=262144} if g<0-262144{g=0-262144} ga[c]=ga[c]+g; c=c+1 } i=i+1 } 87 b=b+1 88 } 89 i=0 90 while i<8 { let ar: *i64=W[i] as *i64; let ga: *i64=gacc[i] as *i64; let cn: i64=WN[i]; var c: i64=0; while c<cn { gb[c]=ga[c]/B; c=c+1 } nfa_sgd(ar,gb,cn,lr); i=i+1 } 91 s=s+1 92 } 93 return 0 94} 95func eval_ce(tape: *i64, vals: *i64, st: *i64, W: *i64, S: *i64, tgt: *i64, P: i64, dm: i64, ffn: i64, V: i64, scale: i64, lv: *i64, N: i64, sdat: *i64) -> i64 { 96 var acc: i64=0; var e: i64=0 97 while e<N { make_stream4(S,tgt,P,sdat); let nl: i64=clm_ffn(tape,vals,st,W,S,tgt,P-1,dm,ffn,V,scale,lv); acc=acc+nfa_val(tape,vals,nl,0); e=e+1 } 98 let mq: i64=acc/N 99 return (mq*1000)/Q16 100} 101 102func main() -> i64 { 103 let ctr: *i64 = gv_ctr() 104 gv_head("nx_nofloat_scale_wide gate (R4 SCALE: WIDTH dm=64 + FFN-complete + batch on the richer grammar) -- SUBJECT: nx_nofloat_autograd, the pure-integer autograd engine" as *u8) 105 let V: i64=16; let P: i64=16; let dm: i64=64; let ffn: i64=128; let scale: i64=8192 106 let tape: *i64=sys_mmap(2048*7*8) as *i64 107 let vals: *i64=sys_mmap(524288*8) as *i64 108 let grads: *i64=sys_mmap(524288*8) as *i64 109 let st: *i64=sys_mmap(2*8) as *i64 110 let nW: i64=8 111 let W: *i64=sys_mmap(nW*8) as *i64; let WN: *i64=sys_mmap(nW*8) as *i64 112 WN[0]=V*dm; WN[1]=dm*dm; WN[2]=dm*dm; WN[3]=dm*dm; WN[4]=dm*dm; WN[5]=dm*ffn; WN[6]=ffn*dm; WN[7]=dm*V 113 var wi: i64=0; while wi<nW { let a: *i64=sys_mmap(WN[wi]*8) as *i64; dini(a,WN[wi],wi+1); W[wi]=a as i64; wi=wi+1 } 114 let gacc: *i64=sys_mmap(nW*8) as *i64; wi=0; while wi<nW { gacc[wi]=(sys_mmap(WN[wi]*8) as *i64) as i64; wi=wi+1 } 115 let lv: *i64=sys_mmap(10*8) as *i64; let gbuf: *i64=sys_mmap(16384*8) as *i64 116 let S: *i64=sys_mmap(P*8) as *i64; let tgt: *i64=sys_mmap(P*8) as *i64; let sdat: *i64=sys_mmap(8) as *i64 117 118 g_puts(" WIDTH scale: dm=64, ffn=128, complete block, batch B=16, SGD lr=0.2, 2500 outer steps (~40k forwards)\n" as *u8) 119 sdat[0]=12345 120 do_train_batch(tape,vals,grads,st,W,WN,gacc,S,tgt,P,dm,ffn,V,scale,lv,gbuf,2500,16,13107,sdat) 121 sdat[0]=24682468 122 let ce: i64=eval_ce(tape,vals,st,W,S,tgt,P,dm,ffn,V,scale,lv,150,sdat) 123 124 g_puts(" [measure] held-out CE="); g_pn(ce); g_puts(" milli-nats uniform=2773 floor=1324 (dm=32 plateaued ~2135)\n") 125 126 var t1: i64=0; if ce*T1_UNIFORM_FRAC_DEN <= UNIFORM_MNAT*T1_UNIFORM_FRAC_NUM { t1=1 } 127 gv_check("T1: held-out CE << uniform (the wide model learned the richer language)" as *u8, t1, ctr) 128 var t2: i64=0; if ce <= FLOOR_MNAT+T2_NEAR_FLOOR_TOL_MNAT { t2=1 } 129 gv_check("T2: held-out CE ~= floor (near-OPTIMAL -> WIDTH-scale closes the richer floor -> R4 progresses)" as *u8, t2, ctr) 130 131 let rc: i64 = gv_verdict("NOFLOAT-SCALE-WIDE-GATE" as *u8, ctr, "WIDTH scale-up reached the richer floor -- scale IS the lever, R4 progresses, pure no-float" as *u8) 132 // The status line is now written ONLY on a GREEN. It used to be appended on every run, pass or fail, so 133 // the log could not distinguish a run that proved something from one that disproved it. 134 // Length DERIVED from the literal via gv_cat -- never hand-counted beside the string it measures. 135 if rc == 0 { 136 let logf: i64 = sys_openat_append("knowledge/status/nofloat_scale_wide.log" as *u8, GV_MODE_644) 137 if logf >= 0 { 138 let ln: *u8 = sys_mmap(GV_LINE) 139 let n: i64 = gv_cat(ln, 0, "NOFLOATSCALEWIDE dm64 width scale-up measured\n" as *u8) 140 sys_write(logf, ln, n) 141 sys_close(logf) 142 sys_munmap(ln, GV_LINE) 143 } 144 } 145 sys_exit(rc) 146 return rc 147}