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}