nx_abs_ab.nx source
↩ module page · 94 lines · 3322 B
1// nx_abs_ab.nx -- rigorous SAME-PROCESS A/B of branchy vs branchless abs in
2// the jitter update. Both variants run the IDENTICAL work (only the abs
3// differs), measured INTERLEAVED with min-of-K so between-batch system-load
4// drift and upward noise cancel (RACING_TEAM_BENCHMARK_DOCTRINE: separate
5// signal from confound; min is the least-disturbed estimate). This is the
6// honest way to decide a ~2-cycle question -- single-run amortized numbers
7// across separate processes are dominated by load variance, not the code.
8//
9// license_tier: ORIGINAL
10
11import "nx_syscalls.nx"
12const K_MAGIC_2654435761: i64 = 2654435761
13const K_MAGIC_2000000: i64 = 2000000
14const K_MAGIC_200000: i64 = 200000
15const K_MAGIC_1000000000000: i64 = 1000000000000
16
17func bdec(n: i64) -> i64 {
18 if n == 0 { sys_write(1, "0" as *u8, 1); return 0 }
19 var m: i64 = n
20 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
21 let d: *u8 = sys_mmap(24)
22 var k: i64 = 0
23 while m > 0 { d[k] = (0x30 + (m % 10)) as u8; m = m / 10; k = k + 1 }
24 var i: i64 = k - 1
25 while i >= 0 { let one: *u8 = sys_mmap(1); one[0] = d[i]; sys_write(1, one, 1); i = i - 1 }
26 return 0
27}
28
29// branchy: if d<0 { d = -d }. Returns elapsed reference cycles for N iters.
30func run_branchy(n: i64) -> i64 {
31 var jit: i64 = 0
32 var prev: i64 = 0
33 let c0: i64 = __rdtsc()
34 var i: i64 = 0
35 while i < n {
36 let off: i64 = ((i * K_MAGIC_2654435761) >> 13) & 63
37 let transit: i64 = 10 + off
38 var d: i64 = transit - prev
39 prev = transit
40 if d < 0 { d = 0 - d }
41 jit = jit + (d - (jit >> 4))
42 i = i + 1
43 }
44 let c1: i64 = __rdtsc()
45 if jit < 0 { return 0 - 1 } // anti-fold
46 return c1 - c0
47}
48
49// branchless: s = d>>63; d = (d^s)-s.
50func run_free(n: i64) -> i64 {
51 var jit: i64 = 0
52 var prev: i64 = 0
53 let c0: i64 = __rdtsc()
54 var i: i64 = 0
55 while i < n {
56 let off: i64 = ((i * K_MAGIC_2654435761) >> 13) & 63
57 let transit: i64 = 10 + off
58 var d: i64 = transit - prev
59 prev = transit
60 let s: i64 = d >> 63
61 d = (d ^ s) - s
62 jit = jit + (d - (jit >> 4))
63 i = i + 1
64 }
65 let c1: i64 = __rdtsc()
66 if jit < 0 { return 0 - 1 }
67 return c1 - c0
68}
69
70func main() -> i64 {
71 let N: i64 = K_MAGIC_2000000
72 let REPS: i64 = 25
73
74 // warmup both (discarded)
75 run_branchy(K_MAGIC_200000); run_free(K_MAGIC_200000)
76
77 var bmin: i64 = K_MAGIC_1000000000000
78 var fmin: i64 = K_MAGIC_1000000000000
79 var k: i64 = 0
80 while k < REPS {
81 let b: i64 = run_branchy(N) // interleaved: same load state
82 if b < bmin { bmin = b }
83 let f: i64 = run_free(N)
84 if f < fmin { fmin = f }
85 k = k + 1
86 }
87
88 sys_write(1, "ABS A/B (same process, interleaved, min of ", 43); bdec(REPS); sys_write(1, " reps, N=", 9); bdec(N); sys_write(1, ")\n", 2)
89 sys_write(1, " branchy (if d<0): ", 21); bdec((bmin * 100) / N); sys_write(1, " cyc/op (x100)\n", 15)
90 sys_write(1, " branchless (d^s)-s: ", 22); bdec((fmin * 100) / N); sys_write(1, " cyc/op (x100)\n", 15)
91 let diff: i64 = ((bmin - fmin) * 100) / N
92 sys_write(1, " delta (branchy - branchless): ", 32); bdec(diff); sys_write(1, " cyc/op (x100); >0 means branchless faster\n", 43)
93 return 0
94}