code wiki / (root) / nx_par_matmul.nx

nx_par_matmul.nx source

↩ module page · 96 lines · 4311 B

1// nx_par_matmul.nx -- SOVEREIGN CPU parallelism: matmul across all cores via fork + shared memory, NO 3rd 2// party (operator: "no 3rd party, nishi ecosystem from the hardware rung up"). Pure syscalls -- sys_fork + 3// sys_mmap_shared (children write row-slices of C into shared mem) + sys_wait4 (parent joins). Inner MAC = 4// sovereign SSE (__f32_mul/__f32_add, nx_f32_hw). This is the tractable sovereign speed lever for the forward 5// (the matmul is the bottleneck): serial vs N-worker parallel, measured, bit-verified. license_tier: ORIGINAL 6import "nx_syscalls.nx" 7import "nx_f32.nx" 8import "nx_f32_hw.nx" 9 10const PM_M: i64 = 384 11const PM_K: i64 = 384 12const PM_N: i64 = 384 13const PM_NW: i64 = 8 // worker forks (>= cores -> measures effective parallelism) 14 15func pm_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 pm_putn(v: i64) -> i64 { 17 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 } 18 var m: i64 = v 19 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 20 let d: *u8 = sys_mmap(24); var k: i64 = 0 21 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 22 var j: i64 = k - 1 23 while j >= 0 { sys_write(1, ((d as i64)+j) as *u8, 1); j = j - 1 } 24 return 0 25} 26 27// C[lo..hi) rows = A[MxK] * B[KxN], sovereign SSE inner. (each worker owns a disjoint row range -> no races) 28func matmul_rows(A: *i64, B: *i64, C: *i64, K: i64, N: i64, lo: i64, hi: i64) -> i64 { 29 var i: i64 = lo 30 while i < hi { 31 var j: i64 = 0 32 while j < N { 33 var acc: i64 = 0 34 var k: i64 = 0 35 while k < K { acc = __f32_add(acc, __f32_mul(A[i * K + k], B[k * N + j])); k = k + 1 } 36 C[i * N + j] = acc 37 j = j + 1 38 } 39 i = i + 1 40 } 41 return 0 42} 43 44func main() -> i64 { 45 let A: *i64 = sys_mmap(PM_M * PM_K * 8) as *i64 46 let B: *i64 = sys_mmap(PM_K * PM_N * 8) as *i64 47 var i: i64 = 0 48 while i < PM_M * PM_K { A[i] = f32_of((i % 5) - 2); i = i + 1 } 49 i = 0 50 while i < PM_K * PM_N { B[i] = f32_of((i % 7) - 3); i = i + 1 } 51 52 // ---- SERIAL (one core) ---- 53 let Cser: *i64 = sys_mmap(PM_M * PM_N * 8) as *i64 54 let t0: i64 = sys_now_ms() 55 matmul_rows(A, B, Cser, PM_K, PM_N, 0, PM_M) 56 let serial_ms: i64 = sys_now_ms() - t0 57 58 // ---- PARALLEL (fork PM_NW workers, each a row-slice, into SHARED C) ---- 59 let Cpar: *i64 = sys_mmap_shared(PM_M * PM_N * 8) as *i64 60 let t1: i64 = sys_now_ms() 61 var w: i64 = 0 62 while w < PM_NW { 63 let pid: i64 = sys_fork() 64 if pid == 0 { 65 let lo: i64 = (w * PM_M) / PM_NW 66 let hi: i64 = ((w + 1) * PM_M) / PM_NW 67 matmul_rows(A, B, Cpar, PM_K, PM_N, lo, hi) 68 sys_exit(0) 69 } 70 w = w + 1 71 } 72 let stp: *i64 = sys_mmap(8) as *i64 73 var d: i64 = 0 74 while d < PM_NW { sys_wait4(0 - 1, stp, 0); d = d + 1 } 75 let par_ms: i64 = sys_now_ms() - t1 76 77 // ---- verify bit-identical ---- 78 var mism: i64 = 0 79 i = 0 80 while i < PM_M * PM_N { if Cpar[i] != Cser[i] { mism = mism + 1 } i = i + 1 } 81 82 pm_puts("=== nx_par_matmul: SOVEREIGN fork-parallel matmul (no 3rd party; fork+shared-mem+SSE) ===\n") 83 pm_puts(" "); pm_putn(PM_M); pm_puts("x"); pm_putn(PM_K); pm_puts("x"); pm_putn(PM_N) 84 pm_puts(" matmul, "); pm_putn(PM_NW); pm_puts(" fork-workers\n") 85 pm_puts(" serial = "); pm_putn(serial_ms); pm_puts(" ms\n") 86 pm_puts(" parallel= "); pm_putn(par_ms); pm_puts(" ms\n") 87 if par_ms > 0 { pm_puts(" speedup = "); pm_putn((serial_ms * 100) / par_ms); pm_puts(" /100x ("); pm_putn(serial_ms / par_ms); pm_puts("x)\n") } 88 pm_puts(" mismatches vs serial = "); pm_putn(mism); pm_puts(" (0 = bit-identical)\n") 89 90 var pass: i64 = 0 91 if mism == 0 { pm_puts(" T1 parallel result bit-identical to serial: PASS\n"); pass = pass + 1 } else { pm_puts(" T1: FAIL\n") } 92 if par_ms < serial_ms { pm_puts(" T2 parallel faster than serial (real sovereign speedup): PASS\n"); pass = pass + 1 } else { pm_puts(" T2: FAIL\n") } 93 pm_puts("\n PASS="); pm_putn(pass); pm_puts("/2 ") 94 if pass == 2 { pm_puts("VERDICT=GREEN (sovereign multicore speedup, no 3rd party -- fork+shared-mem+SSE)\n"); sys_exit(0); return 0 } 95 pm_puts("VERDICT=RED\n"); sys_exit(1); return 1 96}