code wiki / _hdl_build / nx_f32_hw_matmul_curve.nx

nx_f32_hw_matmul_curve.nx source

↩ module page · 56 lines · 2502 B

1// nx_f32_hw_matmul_curve.nx -- diagnose the matmul bottleneck (compute- vs memory-bound). 2// 3// Times the hardware-float GEMM across growing N (matrices grow from L1- to beyond-L2-resident) and 4// reports MFLOP/s per size. The SHAPE of the curve names the next lever, evidence-first: 5// * FLAT across N -> compute-bound on the scalar f32 MAC -> packed SIMD (addps/mulps, 4-wide) is 6// the ~4x lever (needs the sovereign compiler extension: parse+IR+x86 backend). 7// * DROPS at large N -> memory/cache-bound -> transpose-B + cache blocking is the lever (pure .nx). 8// In-organ clock (sys_now_ms), sovereign. license_tier: ORIGINAL 9import "nx_f32_hw_matmul.nx" 10import "nx_syscalls.nx" 11const K_MAGIC_65536: i64 = 65536 12const K_MAGIC_1024: i64 = 1024 13 14func time_hw(A: *i64, B: *i64, C: *i64, N: i64) -> i64 { 15 var reps: i64 = 1; var dt: i64 = 0; var go: i64 = 1 16 while go == 1 { 17 let t0: i64 = sys_now_ms() 18 var r: i64 = 0 19 while r < reps { nx_f32_hw_matmul(A, B, C, N, N, N); r = r + 1 } 20 let t1: i64 = sys_now_ms() 21 dt = t1 - t0 22 if dt >= 60 { go = 0 } else { if reps >= K_MAGIC_65536 { go = 0 } else { reps = reps * 2 } } 23 } 24 if dt <= 0 { dt = 1 } 25 let macs: i64 = N * N * N * reps 26 return (2 * macs) / (dt * 1000) 27} 28func run(N: i64) -> i64 { 29 let A: *i64 = sys_mmap(N * N * 8) as *i64 30 let B: *i64 = sys_mmap(N * N * 8) as *i64 31 let C: *i64 = sys_mmap(N * N * 8) as *i64 32 var i: i64 = 0 33 while i < N * N { A[i] = f32_of(2); B[i] = f32_of(2); i = i + 1 } 34 let mf: i64 = time_hw(A, B, C, N) 35 let kb: i64 = (N * N * 4) / K_MAGIC_1024 36 hmm_puts(" N="); hmm_putn(N); hmm_puts(" (B="); hmm_putn(kb); hmm_puts("KB) hw="); hmm_putn(mf); hmm_puts(" MFLOP/s\n") 37 return mf 38} 39 40func main() -> i64 { 41 hmm_puts("=== hardware f32 GEMM perf curve (bottleneck diagnosis) ===\n") 42 let m32: i64 = run(32) 43 run(64) 44 run(128) 45 run(256) 46 let m512: i64 = run(512) 47 // diagnosis: is large-N within 70% of small-N? (flat => compute-bound) 48 hmm_puts(" DIAGNOSIS: ") 49 if m512 * 100 >= m32 * 70 { 50 hmm_puts("FLAT -> COMPUTE-bound on the scalar f32 MAC -> packed SIMD (addps/mulps) is the ~4x lever\n") 51 } else { 52 hmm_puts("DROPS at large N -> MEMORY/cache-bound -> transpose-B + blocking is the lever (pure .nx)\n") 53 } 54 hmm_puts(" (packed SIMD needs the sovereign compiler extension: __f32x4 intrinsic in parse+IR+x86 backend.)\n") 55 sys_exit(0); return 0 56}