code wiki / (root) / nx_bandwidth_ladder.nx

nx_bandwidth_ladder.nx source

↩ module page · 68 lines · 4514 B

1// nx_bandwidth_ladder.nx -- GENEALOGIST physics grade, 3rd axis: MEMORY BANDWIDTH (for streaming ops). 2// Latency is the floor for random lookups (graded: at it). FLOP is the floor for compute (graded: ~468x off). 3// BANDWIDTH is the floor for STREAMING -- scans, fills, copies, framebuffer clears, segment reads: you cannot 4// process a stream faster than memory delivers it. This measures read bandwidth on a 128MB array (> any cache, 5// so DRAM-bound) single-thread and multicore (fork: more cores saturate more memory channels toward the DRAM 6// ceiling), proves the multicore sum is bit-identical to serial, and grades streaming at the bandwidth floor. 7// Sovereign: sys_mmap_shared + sys_fork + sys_wait4 + sys_now_us. 8// KAT: bandwidth measured; multicore saturates MORE than single-thread (channel parallelism); sums identical. 9// No hw writes (Rule 26). expect_exit: 0 license_tier: ORIGINAL 10import "nx_syscalls.nx" 11const K_MAGIC_16000000: i64 = 16000000 12 13func bw_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 14func bw_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 } 15 16// sum elements [lo,hi) of arr (a streaming read = bandwidth-bound) 17func bw_sum(arr: *i64, lo: i64, hi: i64) -> i64 { var s: i64=0; var i: i64=lo; while i<hi { s=s+arr[i]; i=i+1 } return s } 18 19func main() -> i64 { 20 bw_puts("GENEALOGIST physics grade, axis 3: MEMORY BANDWIDTH (the floor for streaming/scan/fill)\n" as *u8) 21 let N: i64=K_MAGIC_16000000 // 16M x 8B = 128MB (> LLC -> DRAM-bound) 22 let arr: *i64 = sys_mmap_shared(N*8) as *i64 23 var i: i64=0 24 while i<N { arr[i]=i; i=i+1 } 25 let bytes: i64 = N*8 26 27 // single-thread streaming read 28 let t0: i64=sys_now_us() 29 let s_serial: i64 = bw_sum(arr, 0, N) 30 let t1: i64=sys_now_us() 31 var st_us: i64=t1-t0 32 if st_us<=0 { st_us=1 } 33 34 // multicore streaming read: fork NW workers, each sums a slice into shared partials 35 let NW: i64=8 36 let partials: *i64 = sys_mmap_shared(NW*8) as *i64 37 let pids: *i64 = sys_mmap(NW*8) as *i64 38 let t2: i64=sys_now_us() 39 var w: i64=0 40 while w<NW { let pid: i64=sys_fork(); if pid==0 { partials[w]=bw_sum(arr, w*N/NW, (w+1)*N/NW); sys_exit(0) } else { pids[w]=pid; w=w+1 } } 41 w=0 42 let stx: *i64=sys_mmap(8) as *i64 43 while w<NW { sys_wait4(pids[w], stx, 0); w=w+1 } 44 var s_par: i64=0 45 w=0 46 while w<NW { s_par=s_par+partials[w]; w=w+1 } 47 let t3: i64=sys_now_us() 48 var mt_us: i64=t3-t2 49 if mt_us<=0 { mt_us=1 } 50 51 let st_mbs: i64 = bytes/st_us // MB/s = bytes/microsecond 52 let mt_mbs: i64 = bytes/mt_us 53 let scale10: i64 = st_us*10/mt_us 54 55 bw_puts(" single-thread read = "); bw_num(st_mbs); bw_puts(" MB/s ("); bw_num(st_mbs/1000); bw_puts(" GB/s) | "); bw_num(NW); bw_puts("-core read = "); bw_num(mt_mbs); bw_puts(" MB/s ("); bw_num(mt_mbs/1000); bw_puts(" GB/s)\n" as *u8) 56 bw_puts(" multicore saturates "); bw_num(scale10/10); bw_puts("."); bw_num(scale10%10); bw_puts("x more memory bandwidth (channel parallelism toward the DRAM ceiling)\n" as *u8) 57 bw_puts(" => streaming is BANDWIDTH-BOUND: a scan/fill/copy at "); bw_num(mt_mbs/1000); bw_puts(" GB/s is at the memory physics floor; faster needs faster RAM, not better code\n\n" as *u8) 58 59 var pass: i64=0 60 var ttl: i64=0 61 ttl=ttl+1; bw_puts(" T1 bandwidth measured (>0 MB/s, single + multi): " as *u8); if st_mbs>0 { if mt_mbs>0 { pass=pass+1; bw_puts("PASS\n" as *u8) } else { bw_puts("FAIL\n" as *u8) } } else { bw_puts("FAIL\n" as *u8) } 62 ttl=ttl+1; bw_puts(" T2 multicore sum BIT-IDENTICAL to serial (correctness): " as *u8); if s_par==s_serial { pass=pass+1; bw_puts("PASS\n" as *u8) } else { bw_puts("FAIL\n" as *u8) } 63 ttl=ttl+1; bw_puts(" T3 multicore saturates MORE bandwidth than 1 thread (channel parallelism): " as *u8); if mt_mbs>st_mbs { pass=pass+1; bw_puts("PASS\n" as *u8) } else { bw_puts("FAIL\n" as *u8) } 64 65 bw_puts("NX-BANDWIDTH-LADDER passed "); bw_num(pass); bw_puts("/"); bw_num(ttl) 66 if pass==ttl { bw_puts(" verdict=GREEN (memory bandwidth = 3rd physics axis measured; streaming graded at the floor)\n" as *u8); sys_exit(0); return 0 } 67 bw_puts(" verdict=RED\n" as *u8); sys_exit(1); return 1 68}