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}