code wiki / _hdl_build / nx_nofloat_deepstack_gate.nx
nx_nofloat_deepstack_gate.nx source
↩ module page · 215 lines · 13668 B
1// nx_nofloat_deepstack_gate.nx -- HARD-EVIDENCE gate that the no-float transformer scales in DEPTH: a
2// 2-BLOCK (depth-2) transformer LM trains end-to-end on next-token prediction, pure integer Q16. Each block is
3// the verified pre-norm block (attn+RoPE+causal-softmax+SwiGLU+residuals); stacking = composing blk forward N
4// times (NO new ops -- depth is pure composition). Trained with the Q16 AdamW optimizer.
5//
6// A1 depth-2 gradcheck wrt Wlm : the LM-head gradient == finite differences.
7// A2 depth-2 gradcheck wrt E : E's gradient flows back through BOTH blocks (the deep-backprop proof) == FD.
8// D neg-control teeth (E, largest component) ; C bit-exact.
9// B the depth-2 LM TRAINS : next-token CE drops substantially (AdamW on E+Wlm through the 2-block stack).
10// (informational) depth-1 vs depth-2 final CE printed for transparency.
11//
12// Evidence -> knowledge/status/nofloat_deepstack.log. Sovereign: nx_nofloat_autograd + nx_syscalls. expect_exit: 0
13import "nx_nofloat_autograd.nx"
14import "nx_syscalls.nx"
15import "nx_gate_emit_lib.nx"
16
17const DLOG: *u8 = "knowledge/status/nofloat_deepstack.log"
18const Q16: i64 = 65536
19
20
21func g_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
22func d_ws(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
23func d_wn(fd: i64, v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(fd,"-" as *u8,1);m=0-m} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(fd,b,k); return 0 }
24func dini(arr: *i64, n: i64, seed: i64) -> i64 { var i: i64=0; while i<n { arr[i] = (((i*7 + seed*13 + 1) % 11) - 5) * 13107; i=i+1 } return 0 }
25
26// ---- depth-D stack LM forward; W = ptr-array [E, Wlm, then per block b: Wq,Wk,Wv,Wo,Wg,Wu,Wd]; leaves[0]=nE,[1]=nWlm ----
27func stack_fwd(tape: *i64, vals: *i64, st: *i64, W: *i64, D: i64, ids: *i64, tgt: *i64, T: i64, dm: i64, ffn: i64, V: i64, scale: i64, leaves: *i64) -> i64 {
28 let E: *i64 = W[0] as *i64; let Wlm: *i64 = W[1] as *i64
29 st[0]=0; st[1]=0
30 let nE: i64 = nfa_leaf(tape,vals,st,V,dm,E,0)
31 let nWlm: i64 = nfa_leaf(tape,vals,st,dm,V,Wlm,0)
32 var cur: i64 = nfa_embed(tape,vals,st,nE,ids,T)
33 var b: i64 = 0
34 while b < D {
35 let base: i64 = 2 + b*7
36 let Wq: *i64 = W[base+0] as *i64; let Wk: *i64 = W[base+1] as *i64; let Wv: *i64 = W[base+2] as *i64; let Wo: *i64 = W[base+3] as *i64
37 let Wg: *i64 = W[base+4] as *i64; let Wu: *i64 = W[base+5] as *i64; let Wd: *i64 = W[base+6] as *i64
38 let nWq: i64 = nfa_leaf(tape,vals,st,dm,dm,Wq,0)
39 let nWk: i64 = nfa_leaf(tape,vals,st,dm,dm,Wk,0)
40 let nWv: i64 = nfa_leaf(tape,vals,st,dm,dm,Wv,0)
41 let nWo: i64 = nfa_leaf(tape,vals,st,dm,dm,Wo,0)
42 let nWg: i64 = nfa_leaf(tape,vals,st,dm,ffn,Wg,0)
43 let nWu: i64 = nfa_leaf(tape,vals,st,dm,ffn,Wu,0)
44 let nWd: i64 = nfa_leaf(tape,vals,st,ffn,dm,Wd,0)
45 let nXn: i64 = nfa_rmsnorm_rows(tape,vals,st,cur)
46 let nQ: i64 = nfa_matmul(tape,vals,st,nXn,nWq)
47 let nK: i64 = nfa_matmul(tape,vals,st,nXn,nWk)
48 let nV: i64 = nfa_matmul(tape,vals,st,nXn,nWv)
49 let nQr: i64 = nfa_rope(tape,vals,st,nQ)
50 let nKr: i64 = nfa_rope(tape,vals,st,nK)
51 let nS: i64 = nfa_matmul_nt(tape,vals,st,nQr,nKr)
52 let nSs: i64 = nfa_cmul(tape,vals,st,nS,scale)
53 let nA: i64 = nfa_softmax_rows(tape,vals,st,nSs,1)
54 let nO: i64 = nfa_matmul(tape,vals,st,nA,nV)
55 let nOp: i64 = nfa_matmul(tape,vals,st,nO,nWo)
56 let nH: i64 = nfa_vadd(tape,vals,st,cur,nOp)
57 let nHn: i64 = nfa_rmsnorm_rows(tape,vals,st,nH)
58 let nG: i64 = nfa_matmul(tape,vals,st,nHn,nWg)
59 let nU: i64 = nfa_matmul(tape,vals,st,nHn,nWu)
60 let nSg: i64 = nfa_silu(tape,vals,st,nG)
61 let nHs: i64 = nfa_hadamard(tape,vals,st,nSg,nU)
62 let nDp: i64 = nfa_matmul(tape,vals,st,nHs,nWd)
63 cur = nfa_vadd(tape,vals,st,nH,nDp)
64 b = b + 1
65 }
66 let nYn: i64 = nfa_rmsnorm_rows(tape,vals,st,cur)
67 let nLg: i64 = nfa_matmul(tape,vals,st,nYn,nWlm)
68 let nLoss: i64 = nfa_softce_rows(tape,vals,st,nLg,tgt)
69 leaves[0]=nE; leaves[1]=nWlm
70 return nLoss
71}
72func stack_lossval(tape: *i64, vals: *i64, st: *i64, W: *i64, D: i64, ids: *i64, tgt: *i64, T: i64, dm: i64, ffn: i64, V: i64, scale: i64) -> i64 {
73 let lv: *i64 = sys_mmap(2*8) as *i64
74 let nLoss: i64 = stack_fwd(tape,vals,st,W,D,ids,tgt,T,dm,ffn,V,scale,lv)
75 return nfa_val(tape,vals,nLoss,0)
76}
77// gradcheck a leaf weight array (widx: 0=E via leaves[0], 1=Wlm via leaves[1]); extract analytic grads first.
78func stack_gc(tape: *i64, vals: *i64, grads: *i64, st: *i64, W: *i64, D: i64, ids: *i64, tgt: *i64, T: i64, dm: i64, ffn: i64, V: i64, scale: i64, leaves: *i64, lidx: i64, arr: *i64, cnt: i64, h: i64, tol_q: i64, floor_q: i64, worst: *i64, anabuf: *i64) -> i64 {
79 let nLoss: i64 = stack_fwd(tape,vals,st,W,D,ids,tgt,T,dm,ffn,V,scale,leaves)
80 nfa_backward(tape,vals,grads,st[0],nLoss)
81 let nnode: i64 = leaves[lidx]
82 var c: i64=0
83 while c<cnt { anabuf[c]=nfa_grad(tape,grads,nnode,c); c=c+1 }
84 var ok: i64=1; worst[0]=0
85 var i: i64=0
86 while i<cnt {
87 let old: i64=arr[i]
88 arr[i]=old+h; let lp: i64=stack_lossval(tape,vals,st,W,D,ids,tgt,T,dm,ffn,V,scale)
89 arr[i]=old-h; let lm2: i64=stack_lossval(tape,vals,st,W,D,ids,tgt,T,dm,ffn,V,scale)
90 arr[i]=old
91 let fd: i64=((lp-lm2)*Q16)/(2*h); let num: i64=g_abs(fd-anabuf[i]); var den: i64=g_abs(anabuf[i]); if den<floor_q{den=floor_q}
92 if num >= ((tol_q*den)>>16) { ok=0 }
93 let rel: i64=(num*1000)/den; if rel>worst[0]{worst[0]=rel}
94 i=i+1
95 }
96 return ok
97}
98// train E + Wlm with AdamW for `steps`; returns final CE; *lf0 = first CE.
99func stack_train(tape: *i64, vals: *i64, grads: *i64, st: *i64, W: *i64, D: i64, ids: *i64, tgt: *i64, T: i64, dm: i64, ffn: i64, V: i64, scale: i64, steps: i64, lf0: *i64) -> i64 {
100 let E: *i64 = W[0] as *i64; let Wlm: *i64 = W[1] as *i64
101 let gE: *i64 = sys_mmap(64*8) as *i64; let mE: *i64 = sys_mmap(64*8) as *i64; let vE: *i64 = sys_mmap(64*8) as *i64
102 let gL: *i64 = sys_mmap(64*8) as *i64; let mL: *i64 = sys_mmap(64*8) as *i64; let vL: *i64 = sys_mmap(64*8) as *i64
103 var z: i64=0; while z<V*dm { mE[z]=0; vE[z]=0; z=z+1 } z=0; while z<dm*V { mL[z]=0; vL[z]=0; z=z+1 }
104 let leaves: *i64 = sys_mmap(2*8) as *i64
105 var ll: i64=0
106 var ep: i64=0
107 while ep < steps {
108 let nLoss: i64 = stack_fwd(tape,vals,st,W,D,ids,tgt,T,dm,ffn,V,scale,leaves)
109 nfa_backward(tape,vals,grads,st[0],nLoss)
110 if ep==0 { *lf0 = nfa_val(tape,vals,nLoss,0) }
111 ll = nfa_val(tape,vals,nLoss,0)
112 let nE: i64=leaves[0]; z=0; while z<V*dm { gE[z]=nfa_grad(tape,grads,nE,z); z=z+1 }
113 nfa_adamw(E, gE, mE, vE, V*dm, 3277, 58982, 65470, 66, 0, ep+1)
114 let nWl: i64=leaves[1]; z=0; while z<dm*V { gL[z]=nfa_grad(tape,grads,nWl,z); z=z+1 }
115 nfa_adamw(Wlm, gL, mL, vL, dm*V, 3277, 58982, 65470, 66, 0, ep+1)
116 ep=ep+1
117 }
118 return ll
119}
120// build a fresh weight pointer-array of D blocks, all arrays freshly mmap'd + init'd (deterministic).
121func build_W(D: i64, dm: i64, ffn: i64, V: i64) -> *i64 {
122 let W: *i64 = sys_mmap((2 + D*7)*8) as *i64
123 let E: *i64 = sys_mmap(V*dm*8) as *i64; dini(E,V*dm,1); W[0]=E as i64
124 let Wlm: *i64 = sys_mmap(dm*V*8) as *i64; dini(Wlm,dm*V,2); W[1]=Wlm as i64
125 var b: i64=0
126 while b<D {
127 let base: i64 = 2 + b*7
128 let Wq: *i64=sys_mmap(dm*dm*8) as *i64; dini(Wq,dm*dm,10+b*7+0); W[base+0]=Wq as i64
129 let Wk: *i64=sys_mmap(dm*dm*8) as *i64; dini(Wk,dm*dm,10+b*7+1); W[base+1]=Wk as i64
130 let Wv: *i64=sys_mmap(dm*dm*8) as *i64; dini(Wv,dm*dm,10+b*7+2); W[base+2]=Wv as i64
131 let Wo: *i64=sys_mmap(dm*dm*8) as *i64; dini(Wo,dm*dm,10+b*7+3); W[base+3]=Wo as i64
132 let Wg: *i64=sys_mmap(dm*ffn*8) as *i64; dini(Wg,dm*ffn,10+b*7+4); W[base+4]=Wg as i64
133 let Wu: *i64=sys_mmap(dm*ffn*8) as *i64; dini(Wu,dm*ffn,10+b*7+5); W[base+5]=Wu as i64
134 let Wd: *i64=sys_mmap(ffn*dm*8) as *i64; dini(Wd,ffn*dm,10+b*7+6); W[base+6]=Wd as i64
135 b=b+1
136 }
137 return W
138}
139
140func main() -> i64 {
141 g_puts("nx_nofloat_deepstack gate (a DEPTH-2 transformer LM trains end-to-end, PURE INTEGER Q16)\n" as *u8)
142 var pass: i64=0; var total: i64=0
143 let tape: *i64 = sys_mmap(1024*7*8) as *i64
144 let vals: *i64 = sys_mmap(32768*8) as *i64
145 let grads: *i64 = sys_mmap(32768*8) as *i64
146 let st: *i64 = sys_mmap(2*8) as *i64
147 let h: i64=512; let floor_q: i64=4096
148 let worst: *i64 = sys_mmap(8) as *i64
149 let anabuf: *i64 = sys_mmap(64*8) as *i64
150 let T: i64=4; let dm: i64=4; let ffn: i64=8; let V: i64=4; let scale: i64=32768; let D: i64=2
151 let ids: *i64 = sys_mmap(T*8) as *i64; ids[0]=0; ids[1]=1; ids[2]=2; ids[3]=3
152 let tgt: *i64 = sys_mmap(T*8) as *i64; tgt[0]=1; tgt[1]=2; tgt[2]=3; tgt[3]=0
153 let leaves: *i64 = sys_mmap(2*8) as *i64
154
155 // ---- A1: depth-2 gradcheck wrt Wlm ----
156 let Wa: *i64 = build_W(D,dm,ffn,V)
157 let a1_ok: i64 = stack_gc(tape,vals,grads,st,Wa,D,ids,tgt,T,dm,ffn,V,scale,leaves,1,Wa[1] as *i64,dm*V,h,8192,floor_q,worst,anabuf)
158 g_puts(" [measure] depth-2 dL/dWlm worst rel grad err = " as *u8); g_pn(worst[0]); g_puts(" /1000 (tol=125)\n" as *u8)
159 pass=pass+g_check("A1: depth-2 gradcheck wrt Wlm (LM head through CE) == finite differences" as *u8, a1_ok); total=total+1
160
161 // ---- A2: depth-2 gradcheck wrt E (through BOTH blocks) ----
162 let a2_ok: i64 = stack_gc(tape,vals,grads,st,Wa,D,ids,tgt,T,dm,ffn,V,scale,leaves,0,Wa[0] as *i64,V*dm,h,16384,floor_q,worst,anabuf)
163 g_puts(" [measure] depth-2 dL/dE (through BOTH blocks) worst rel grad err = " as *u8); g_pn(worst[0]); g_puts(" /1000 (tol=250)\n" as *u8)
164 pass=pass+g_check("A2: depth-2 gradcheck wrt E through BOTH blocks == finite differences (deep backprop)" as *u8, a2_ok); total=total+1
165
166 // ---- D: neg-control teeth (E, largest grad component, scale-free) ----
167 let nLd: i64 = stack_fwd(tape,vals,st,Wa,D,ids,tgt,T,dm,ffn,V,scale,leaves)
168 nfa_backward(tape,vals,grads,st[0],nLd)
169 let Ea: *i64 = Wa[0] as *i64
170 var imax: i64=0; var vmax: i64=0; var ii: i64=0
171 while ii<V*dm { let gg: i64=g_abs(nfa_grad(tape,grads,leaves[0],ii)); if gg>vmax { vmax=gg; imax=ii } ii=ii+1 }
172 let dana: i64 = nfa_grad(tape,grads,leaves[0],imax)
173 let o0: i64=Ea[imax]; Ea[imax]=o0+h; let lpd: i64=stack_lossval(tape,vals,st,Wa,D,ids,tgt,T,dm,ffn,V,scale); Ea[imax]=o0-h; let lmd: i64=stack_lossval(tape,vals,st,Wa,D,ids,tgt,T,dm,ffn,V,scale); Ea[imax]=o0
174 let dfd: i64=((lpd-lmd)*Q16)/(2*h); let dbad: i64=0-dana
175 let dgood: i64=g_abs(dfd-dana); let dneg: i64=g_abs(dfd-dbad)
176 var caught: i64=0; if vmax>64 { if dneg > dgood*4 { caught=1 } }
177 pass=pass+g_check("D: neg-control -- FD is >4x closer to the true E-grad than to the negated one (teeth)" as *u8, caught); total=total+1
178
179 // ---- B: depth-2 LM trains (CE drops) with AdamW ----
180 let Wb: *i64 = build_W(D,dm,ffn,V)
181 let lf2: *i64 = sys_mmap(8) as *i64
182 let ce2: i64 = stack_train(tape,vals,grads,st,Wb,D,ids,tgt,T,dm,ffn,V,scale,3000,lf2)
183 // informational: depth-1 final CE
184 let W1: *i64 = build_W(1,dm,ffn,V)
185 let lf1: *i64 = sys_mmap(8) as *i64
186 let ce1: i64 = stack_train(tape,vals,grads,st,W1,1,ids,tgt,T,dm,ffn,V,scale,3000,lf1)
187 g_puts(" [measure] depth-2 CE: start=" as *u8); g_pn(*lf2); g_puts(" end=" as *u8); g_pn(ce2); g_puts(" (info: depth-1 CE start=" as *u8); g_pn(*lf1); g_puts(" end=" as *u8); g_pn(ce1); g_puts(")\n" as *u8)
188 var fits: i64=1
189 if ce2*2 > (*lf2) { fits=0 } // depth-2 CE drops >= 50%
190 if (*lf2) <= 0 { fits=0 }
191 pass=pass+g_check("B: the DEPTH-2 LM TRAINS end-to-end -- CE drops >=50% (AdamW thru 2 blocks; FITS/memorizes a FIXED sequence, not generalization)" as *u8, fits); total=total+1
192
193 // ---- C: bit-exact (depth-2 trained twice) ----
194 let Wc: *i64 = build_W(D,dm,ffn,V)
195 let lfc: *i64 = sys_mmap(8) as *i64
196 let cec: i64 = stack_train(tape,vals,grads,st,Wc,D,ids,tgt,T,dm,ffn,V,scale,3000,lfc)
197 var bitexact: i64=1
198 let Eb: *i64 = Wb[0] as *i64; let Ec: *i64 = Wc[0] as *i64
199 var bz: i64=0; while bz<V*dm { if Eb[bz]!=Ec[bz] { bitexact=0 } bz=bz+1 }
200 let Wlb: *i64 = Wb[1] as *i64; let Wlc: *i64 = Wc[1] as *i64
201 bz=0; while bz<dm*V { if Wlb[bz]!=Wlc[bz] { bitexact=0 } bz=bz+1 }
202 pass=pass+g_check("C: bit-exact -- training the depth-2 LM twice gives IDENTICAL integer weights (determinism)" as *u8, bitexact); total=total+1
203
204 var okall: i64=0; if pass==total { okall=1 }
205 let logf: i64 = sys_openat_append(DLOG, 420)
206 if logf >= 0 {
207 d_ws(logf,"NOFLOATDEEPSTACK D=2 A1_Wlm=" as *u8); d_wn(logf,a1_ok); d_ws(logf," A2_E_bothblocks=" as *u8); d_wn(logf,a2_ok)
208 d_ws(logf," D=" as *u8); d_wn(logf,caught); d_ws(logf," B_fits=" as *u8); d_wn(logf,fits); d_ws(logf," CE2_start=" as *u8); d_wn(logf,*lf2); d_ws(logf," CE2_end=" as *u8); d_wn(logf,ce2); d_ws(logf," C_bitexact=" as *u8); d_wn(logf,bitexact)
209 if okall==1 { d_ws(logf," verdict=GREEN\n" as *u8) } else { d_ws(logf," verdict=RED\n" as *u8) }
210 sys_close(logf)
211 }
212 g_puts("---- nofloat_deepstack gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8)
213 if okall==1 { g_puts("verdict=GREEN (a depth-2 transformer LM trains end-to-end in pure integer Q16 -- depth scales by composition)\n" as *u8); sys_exit(0); return 0 }
214 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1
215}