code wiki / (root) / nx_compute_mt.nx

nx_compute_mt.nx source

↩ module page · 94 lines · 5016 B

1// nx_compute_mt.nx -- walking up the COMPUTE wall toward physics: MULTICORE matmul (the ~20x lever). 2// The compute physics grade (nx_compute_ladder) found the sovereign matmul ~5000x below the silicon f32 3// peak -- but the peak assumes ALL cores; the matmul used ONE. Multicore is the biggest single lever and 4// needs NO compiler surgery: fork N workers over a SHARED-memory C, each computing a disjoint row band. 5// This measures single-thread vs N-thread on the SAME problem, proves the parallel result is bit-identical 6// to the serial one (correctness across processes), and reports the speedup + how much of the physics gap it 7// closes. Sovereign: sys_fork + sys_mmap_shared + sys_wait4 + nx_f32_hw SSE f32. 8// KAT: parallel result == serial (bit-exact); multicore is faster; speedup + closed gap reported. 9// HONEST: this is the multicore lever only; packed-SIMD (4-8x) + FMA (2x) + blocking still remain (deeper, 10// compiler-side). No hw writes (Rule 26). expect_exit: 0 license_tier: ORIGINAL 11import "nx_f32_hw.nx" 12import "nx_syscalls.nx" 13const K_MAGIC_1842560: i64 = 1842560 14 15func mt_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 16func mt_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 } 17 18// compute rows [w*sz/nw, (w+1)*sz/nw) of C = A @ B (row band; workers write disjoint bands of shared C) 19func mm_band(a: *i64, b: *i64, c: *i64, sz: i64, w: i64, nw: i64) -> i64 { 20 let r0: i64=w*sz/nw 21 let r1: i64=(w+1)*sz/nw 22 var i: i64=r0 23 while i<r1 { 24 var j: i64=0 25 while j<sz { 26 var acc: i64=__f32_from_i64(0) 27 var l: i64=0 28 while l<sz { acc=__f32_add(acc, __f32_mul(a[i*sz+l], b[l*sz+j])); l=l+1 } 29 c[i*sz+j]=acc 30 j=j+1 31 } 32 i=i+1 33 } 34 return 0 35} 36 37func main() -> i64 { 38 mt_puts("walking up the COMPUTE wall: MULTICORE matmul (fork + shared memory, the ~20x lever)\n" as *u8) 39 let SZ: i64=256 40 let NW: i64=8 41 let A: *i64 = sys_mmap_shared(SZ*SZ*8) as *i64 42 let B: *i64 = sys_mmap_shared(SZ*SZ*8) as *i64 43 let C: *i64 = sys_mmap_shared(SZ*SZ*8) as *i64 44 let C0: *i64 = sys_mmap(SZ*SZ*8) as *i64 45 var i: i64=0 46 while i<SZ*SZ { A[i]=f32_of((i%7)+1); B[i]=f32_of((i%5)+1); C[i]=0; i=i+1 } 47 48 // --- single-thread baseline (whole matrix) --- 49 let t0: i64=sys_now_us() 50 mm_band(A, B, C0, SZ, 0, 1) 51 let t1: i64=sys_now_us() 52 var us1: i64=t1-t0 53 if us1<=0 { us1=1 } 54 55 // --- multicore: fork NW workers over shared C --- 56 let pids: *i64 = sys_mmap(NW*8) as *i64 57 let t2: i64=sys_now_us() 58 var w: i64=0 59 while w<NW { 60 let pid: i64=sys_fork() 61 if pid==0 { mm_band(A, B, C, SZ, w, NW); sys_exit(0) } else { pids[w]=pid; w=w+1 } 62 } 63 w=0 64 let st: *i64 = sys_mmap(8) as *i64 65 while w<NW { sys_wait4(pids[w], st, 0); w=w+1 } 66 let t3: i64=sys_now_us() 67 var usN: i64=t3-t2 68 if usN<=0 { usN=1 } 69 70 // correctness: parallel C == serial C0 (bit-exact) 71 var ok: i64=1 72 i=0 73 while i<SZ*SZ { if C[i]!=C0[i] { ok=0 } i=i+1 } 74 75 let flop: i64 = 2*SZ*SZ*SZ 76 let mf1: i64 = flop/us1 77 let mfN: i64 = flop/usN 78 let speedup10: i64 = us1*10/usN 79 let gap_before: i64 = K_MAGIC_1842560/mf1 // x below silicon peak, single-thread 80 let gap_after: i64 = K_MAGIC_1842560/mfN // x below silicon peak, multicore 81 82 mt_puts(" single-thread = "); mt_num(mf1); mt_puts(" MFLOP/s | "); mt_num(NW); mt_puts("-worker multicore = "); mt_num(mfN); mt_puts(" MFLOP/s speedup = "); mt_num(speedup10/10); mt_puts("."); mt_num(speedup10%10); mt_puts("x\n" as *u8) 83 mt_puts(" gap to silicon f32 peak: BEFORE ~"); mt_num(gap_before); mt_puts("x -> AFTER ~"); mt_num(gap_after); mt_puts("x (multicore closed "); mt_num(speedup10/10); mt_puts("x of it; packed-SIMD+FMA+blocking remain)\n" as *u8) 84 85 var pass: i64=0 86 var ttl: i64=0 87 ttl=ttl+1; mt_puts(" T1 parallel result BIT-IDENTICAL to serial (correctness across processes): " as *u8); if ok==1 { pass=pass+1; mt_puts("PASS\n" as *u8) } else { mt_puts("FAIL\n" as *u8) } 88 ttl=ttl+1; mt_puts(" T2 multicore FASTER than single-thread (the lever works): " as *u8); if mfN>mf1 { pass=pass+1; mt_puts("PASS\n" as *u8) } else { mt_puts("FAIL\n" as *u8) } 89 ttl=ttl+1; mt_puts(" T3 measurable speedup (>= 2x): " as *u8); if speedup10>=20 { pass=pass+1; mt_puts("PASS\n" as *u8) } else { mt_puts("FAIL\n" as *u8) } 90 91 mt_puts("NX-COMPUTE-MT-GATE passed "); mt_num(pass); mt_puts("/"); mt_num(ttl) 92 if pass==ttl { mt_puts(" verdict=GREEN (multicore matmul: bit-exact + faster -- a real step up the compute wall toward physics)\n" as *u8); sys_exit(0); return 0 } 93 mt_puts(" verdict=RED\n" as *u8); sys_exit(1); return 1 94}