code wiki / (root) / nx_sum_bench_all.nx

nx_sum_bench_all.nx source

↩ module page · 119 lines · 4295 B

1// nx_sum_bench_all.nx -- comprehensive sum-of-N-i64 bench across 2// all NishiLang paths for cross-language comparison. 3// 4// Same workload as sum_c.c (N=1M i64 sum, 100 reps) but exercises 5// every parallelism axis NishiLang ships: 6// 7// 1. scalar single-thread, no SIMD 8// 2. parallel_reduce MIMD across pool workers 9// 3. SIMD-only i64x4 horizontal reduce in chunks of 4 10// 4. parallel + SIMD per-chunk SIMD reduce, parallel across chunks 11// 12// All paths produce bit-exact results vs the scalar reference. 13// Wall-time numbers are reported but qemu interpretive emulation 14// distorts both MIMD (single-CPU emulator) and SIMD (per-lane 15// interpretive cost), so the wall-time signal is noisy -- see 16// docs/PERF_NISHI_VS_C.md for the honest interpretation. 17 18// nx_safety_envelope: 19// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 20// sil_target: SIL1 21// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 22// verdict: NOT_YET_EVALUATED 23 24import "nx_kernel_v2.nx" 25import "nx_log.nx" 26import "nx_atom.nx" 27import "nx_clock.nx" 28import "nx_thread_pool.nx" 29import "nx_parallel.nx" 30import "nx_hw.nx" 31 32const N: i64 = 1000000 33const REPS: i64 = 10 // fewer reps than C bench -- 34 // qemu interpretive overhead 35 36func scalar_sum(arr: *i64) -> i64 { 37 var s: i64 = 0 38 var i: i64 = 0 39 while i < N { s = s + arr[i]; i = i + 1 } 40 return s 41} 42 43func simd_sum(arr: *i64) -> i64 { 44 var s: i64 = 0 45 var i: i64 = 0 46 while i < N { 47 let p: *i64 = ((arr as i64) + i * 8) as *i64 48 let v: i64 = __simd_vload_i64_x4(p) 49 s = s + __simd_vreduce_sum_i64_x4(v) 50 i = i + 4 51 } 52 return s 53} 54 55func iadd(a: i64, b: i64) -> i64 { return a + b } 56 57func main() -> nx_exit { 58 var nw: i64 = nx_hw_worker_count() 59 if nw < 2 { nw = 2 } 60 let pool: *NxThreadPool = nx_pool_new(nw, 64) 61 62 let raw: *u8 = sys_mmap(N * 8) 63 let arr: *i64 = raw as *i64 64 var k: i64 = 0 65 while k < N { arr[k] = k; k = k + 1 } 66 let expected: i64 = (N - 1) * N / 2 67 68 println("=== nx_sum_bench_all -- all paths over N=1M, 10 reps ===" as *u8) 69 print_i64(nw); println(" pool workers" as *u8) 70 71 // ---- Path 1: scalar ---- 72 let t0_s: i64 = nx_clock_monotonic_ns() 73 var sum_s: i64 = 0 74 var r1: i64 = 0 75 while r1 < REPS { sum_s = sum_s + scalar_sum(arr); r1 = r1 + 1 } 76 let t1_s: i64 = nx_clock_monotonic_ns() 77 if sum_s != expected * REPS { println("FAIL: scalar wrong" as *u8); return 1 } 78 println("scalar ns:" as *u8); print_i64(t1_s - t0_s); println("" as *u8) 79 80 // ---- Path 2: parallel_reduce ---- 81 let t0_p: i64 = nx_clock_monotonic_ns() 82 var sum_p: i64 = 0 83 var r2: i64 = 0 84 while r2 < REPS { 85 sum_p = sum_p + nx_parallel_reduce_i64(pool, arr, N, 0, iadd) 86 r2 = r2 + 1 87 } 88 let t1_p: i64 = nx_clock_monotonic_ns() 89 if sum_p != expected * REPS { println("FAIL: parallel wrong" as *u8); return 2 } 90 println("parallel ns:" as *u8); print_i64(t1_p - t0_p); println("" as *u8) 91 92 // ---- Path 3: SIMD-only ---- 93 let t0_v: i64 = nx_clock_monotonic_ns() 94 var sum_v: i64 = 0 95 var r3: i64 = 0 96 while r3 < REPS { sum_v = sum_v + simd_sum(arr); r3 = r3 + 1 } 97 let t1_v: i64 = nx_clock_monotonic_ns() 98 if sum_v != expected * REPS { println("FAIL: simd wrong" as *u8); return 3 } 99 println("simd ns:" as *u8); print_i64(t1_v - t0_v); println("" as *u8) 100 101 // ---- Path 4: parallel + SIMD (composed) ---- 102 let t0_ps: i64 = nx_clock_monotonic_ns() 103 var sum_ps: i64 = 0 104 var r4: i64 = 0 105 while r4 < REPS { 106 sum_ps = sum_ps + nx_parallel_reduce_sum_simd_i64(pool, arr, N, 0) 107 r4 = r4 + 1 108 } 109 let t1_ps: i64 = nx_clock_monotonic_ns() 110 if sum_ps != expected * REPS { println("FAIL: parallel+simd wrong" as *u8); return 4 } 111 println("par+simd ns:" as *u8); print_i64(t1_ps - t0_ps); println("" as *u8) 112 113 nx_pool_shutdown(pool) 114 println("" as *u8) 115 println("All paths bit-exact (sum == (N-1)*N/2 = 499999500000)." as *u8) 116 println("Wall times under qemu interpretive emulation; see PERF_NISHI_VS_C.md" as *u8) 117 println("for honest interpretation + real-silicon projections." as *u8) 118 return 0 119}