code wiki / (root) / nx_nofloat_gemm_gate.nx

nx_nofloat_gemm_gate.nx source

↩ module page · 103 lines · 5863 B

1// nx_nofloat_gemm_gate.nx -- the NO-FLOAT compute lever: integer SIMD GEMM (vpmaddwd), the deterministic 2// kernel every Nishi model rides. The kernel itself now lives in nx_nofloat_gemm.nx (shared lib, debt-free); 3// this gate exercises it: scalar integer matmul vs SIMD integer matmul MUST be bit-identical (integer add is 4// associative -> exact + deterministic, the no-float exceed axis [[nx_nofloat_exceed_gate]]) and SIMD is faster. 5// No hw writes (Rule 26). expect_exit: 0 license_tier: ORIGINAL 6import "nx_syscalls.nx" 7import "nx_nofloat_gemm.nx" 8import "nx_gate_verdict.nx" 9 10func ng_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 11func ng_num(v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;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(1,b,k); return 0 } 12 13func main() -> i64 { 14 ng_puts("NO-FLOAT compute lever: integer SIMD GEMM (vpmaddwd) -- EXACT + DETERMINISTIC, the kernel models ride\n\n" as *u8) 15 let M: i64=64 16 let N: i64=64 17 let K: i64=256 18 let ai: *i64 = sys_mmap(M*K*8) as *i64 19 let bi: *i64 = sys_mmap(N*K*8) as *i64 20 let a16: *u8 = sys_mmap(M*K*2) 21 let b16: *u8 = sys_mmap(N*K*2) 22 let acc: *u8 = sys_mmap(64) 23 let cs: *i64 = sys_mmap(M*N*8) as *i64 24 let cv: *i64 = sys_mmap(M*N*8) as *i64 25 26 var i: i64=0 27 while i<M { var k: i64=0 28 while k<K { let v: i64=((i+k)%4)+1; ai[i*K+k]=v; pack2(a16, i*K+k, v); k=k+1 } 29 i=i+1 } 30 var j: i64=0 31 while j<N { var k2: i64=0 32 while k2<K { let w: i64=((j+k2)%4)+1; bi[j*K+k2]=w; pack2(b16, j*K+k2, w); k2=k2+1 } 33 j=j+1 } 34 35 scalar_imm(ai, bi, cs, M, N, K) 36 simd_imm(a16, b16, cv, acc, M, N, K) 37 38 var mism: i64=0 39 i=0 40 while i<M { var jj: i64=0 41 while jj<N { if cs[i*N+jj] != cv[i*N+jj] { mism=mism+1 } jj=jj+1 } 42 i=i+1 } 43 let s0: i64=cs[0] 44 let v0: i64=cv[0] 45 var exp: i64=0 46 var kk: i64=0 47 while kk<K { let a: i64=((0+kk)%4)+1; exp=exp+a*a; kk=kk+1 } 48 49 let REPS: i64=50 50 let t0: i64=sys_now_us() 51 var r: i64=0 52 while r<REPS { scalar_imm(ai, bi, cs, M, N, K); r=r+1 } 53 let t1: i64=sys_now_us() 54 var rv: i64=0 55 while rv<REPS { simd_imm(a16, b16, cv, acc, M, N, K); rv=rv+1 } 56 let t2: i64=sys_now_us() 57 var us_s: i64=t1-t0 58 if us_s<=0 { us_s=1 } 59 var us_v: i64=t2-t1 60 if us_v<=0 { us_v=1 } 61 let sp: i64=us_s*100/us_v 62 let mf: i64=2*M*N*K/(us_v/REPS+1) 63 64 ng_puts(" integer matmul "); ng_num(M); ng_puts("x"); ng_num(N); ng_puts("x"); ng_num(K); ng_puts(" out[0][0]: scalar="); ng_num(s0); ng_puts(" simd="); ng_num(v0); ng_puts(" (expected "); ng_num(exp); ng_puts(")\n"); 65 ng_puts(" bit-exact mismatches (simd vs scalar): "); ng_num(mism); ng_puts(" / "); ng_num(M*N); ng_puts("\n"); 66 ng_puts(" scalar-int = "); ng_num(us_s); ng_puts("us SIMD-int (vpmaddwd) = "); ng_num(us_v); ng_puts("us SPEEDUP = "); ng_num(sp/100); ng_puts("."); ng_num((sp%100)/10); ng_num(sp%10); ng_puts("x ("); ng_num(mf); ng_puts(" Mop/s)\n\n"); 67 68 // NEGATIVE-LANE KAT -- regression guard for the i32x8_hsum sign-extend bug. The original data above is all 69 // positive (1..4), so it NEVER exercised a negative int32 lane -> the zero-extend bug hid here for months. 70 // a=+1, b=-100 -> every product -100 -> lane sums NEGATIVE -> pre-fix hsum returned ~4e9 garbage. 71 let na16: *u8 = sys_mmap(K*2) 72 let nb16: *u8 = sys_mmap(K*2) 73 let nacc: *u8 = sys_mmap(64) 74 let ncs: *i64 = sys_mmap(8) as *i64 75 let ncv: *i64 = sys_mmap(8) as *i64 76 let nai: *i64 = sys_mmap(K*8) as *i64 77 let nbi: *i64 = sys_mmap(K*8) as *i64 78 var nk: i64=0 79 while nk<K { nai[nk]=1; nbi[nk]=0-100; pack2(na16, nk, 1); pack2(nb16, nk, 0-100); nk=nk+1 } 80 scalar_imm(nai, nbi, ncs, 1, 1, K) 81 simd_imm(na16, nb16, ncv, nacc, 1, 1, K) 82 let nexp: i64=0-(100*K) 83 ng_puts(" NEGATIVE-lane dot (regression guard): scalar="); ng_num(ncs[0]); ng_puts(" simd="); ng_num(ncv[0]); ng_puts(" (expected "); ng_num(nexp); ng_puts(")\n\n") 84 85 var pass: i64=0 86 var ttl: i64=0 87 ttl=ttl+1; ng_puts(" T1 __i16x16_madd (vpmaddwd via .byte VEX) compiled+ran: "); if v0>0 { pass=pass+1; ng_puts("PASS\n") } else { ng_puts("FAIL\n") } 88 ttl=ttl+1; ng_puts(" T2 EXACT + DETERMINISTIC: SIMD integer == scalar integer BIT-EXACT (0 mismatches): "); if mism==0 { pass=pass+1; ng_puts("PASS\n") } else { ng_puts("FAIL\n") } 89 ttl=ttl+1; ng_puts(" T3 known-answer out[0][0] == "); ng_num(exp); ng_puts(": "); if v0==exp { pass=pass+1; ng_puts("PASS\n") } else { ng_puts("FAIL\n") } 90 ttl=ttl+1; ng_puts(" T4 the no-float lever ACCELERATES (SIMD-int faster than scalar-int): "); if us_v<us_s { pass=pass+1; ng_puts("PASS\n") } else { ng_puts("FAIL\n") } 91 ttl=ttl+1; ng_puts(" T5 NEGATIVE-lane sign-extend (i32x8_hsum bug regression guard) simd==scalar=="); ng_num(nexp); ng_puts(": "); if ncv[0]==nexp { if ncs[0]==nexp { pass=pass+1; ng_puts("PASS\n") } else { ng_puts("FAIL(scalar)\n") } } else { ng_puts("FAIL(simd zero-extended negative lanes)\n") } 92 93 ng_puts("NX-NOFLOAT-GEMM-GATE passed "); ng_num(pass); ng_puts("/"); ng_num(ttl) 94 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 95 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 96 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 97 let ctr__dry: *i64 = gv_ctr() 98 ctr__dry[0] = pass 99 ctr__dry[1] = ttl 100 let rc__dry: i64 = gv_verdict("NOFLOAT-GEMM-GATE" as *u8, ctr__dry, "no-float integer SIMD GEMM: EXACT + DETERMINISTIC + fast -- the deterministic compute lever models ride)" as *u8) 101 sys_exit(rc__dry) 102 return rc__dry 103}