code wiki / _hdl_build / nx_simd_test.nx
nx_simd_test.nx source
↩ module page · 60 lines · 2823 B
1// nx_simd_test.nx -- prove the vectorizing transform is 1:1 with the scalar kernel
2// and measure the op reduction (the SIMD win). The vector loop must produce the
3// IDENTICAL output array to the scalar loop over a real, tail-bearing size, and
4// issue ~N/VW vector ops vs the scalar 2N. Known answer: arrays identical AND vector
5// ops << scalar ops -> exit 0.
6
7import "nx_simd.nx"
8
9func si_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
10func si_num(v: i64) -> i64 {
11 let b: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m }
12 let t: *u8 = sys_mmap(28); var k: i64 = 0
13 if m == 0 { t[0] = 48; k = 1 }
14 while m > 0 { t[k] = 48 + (m % 10); m = m / 10; k = k + 1 }
15 var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 }
16 sys_write(1, b, k); return 0
17}
18
19func main() -> i64 {
20 si_puts("=== SIMD: vectorizing transform proven 1:1 vs scalar, op-reduction measured ===\n" as *u8)
21 let n: i64 = 100 // NOT a multiple of VW=8 -> exercises the tail
22 let a: *i64 = sys_mmap(8 * (n + 16)) as *i64
23 let b: *i64 = sys_mmap(8 * (n + 16)) as *i64
24 let d: *i64 = sys_mmap(8 * (n + 16)) as *i64
25 let cs: *i64 = sys_mmap(8 * (n + 16)) as *i64
26 let cv: *i64 = sys_mmap(8 * (n + 16)) as *i64
27
28 // fill with pseudo-random data
29 var s: i64 = 88172645463325252
30 var i: i64 = 0
31 while i < n {
32 s = s * 6364136223846793005 + 1442695040888963407; a[i] = (s >> 40) & 0xFFFF
33 s = s * 6364136223846793005 + 1442695040888963407; b[i] = (s >> 40) & 0xFFFF
34 s = s * 6364136223846793005 + 1442695040888963407; d[i] = (s >> 40) & 0xFFFF
35 i = i + 1
36 }
37
38 k_scalar(cs, a, b, d, n)
39 let vops: i64 = k_vector(cv, a, b, d, n)
40
41 // 1:1 -- every element must match.
42 var mism: i64 = 0
43 i = 0
44 while i < n { if cv[i] != cs[i] { mism = mism + 1 } i = i + 1 }
45
46 let scalar_ops: i64 = 2 * n // n muls + n adds
47 si_puts(" elements : " as *u8); si_num(n)
48 si_puts(" mismatches (scalar==vec) : " as *u8); si_num(mism)
49 si_puts(" scalar ops (n mul+n add) : " as *u8); si_num(scalar_ops)
50 si_puts(" vector ops issued : " as *u8); si_num(vops)
51 if vops > 0 { si_puts(" op reduction : " as *u8); si_num(scalar_ops / vops); si_puts("x\n" as *u8) }
52 si_puts(" -> one vector op does " as *u8); si_num(VW); si_puts(" lanes; vectorized is correct AND ~VWx fewer ops.\n" as *u8)
53
54 // GATE: identical output, and a real op reduction (vector ops well under scalar).
55 if mism != 0 { sys_exit(1); return 1 }
56 if vops >= scalar_ops { sys_exit(2); return 2 }
57 if vops > (scalar_ops / 4) { sys_exit(3); return 3 } // expect ~VW/2 = 4x+ reduction (2 ops/VW lanes)
58 sys_exit(0)
59 return 0
60}