code wiki / _hdl_build / nx_measure_cost_test.nx

nx_measure_cost_test.nx source

↩ module page · 85 lines · 3381 B

1// nx_measure_cost_test.nx -- the optimizer's cost model from MEASURED REALITY, not 2// a datasheet. The Seed spores onto hardware and TIMES the actual operations 3// (rdtsc cycle counter) to learn THIS machine's real costs -- so a slow/damaged/ 4// asymmetric unit is reflected and the optimizer targets the hardware's true 5// limits. (A board with a crippled divider measures div as expensive and the loop 6// routes around it; a board with fast mul measures that and uses it.) 7// 8// Universal-reality invariant (true on every real CPU): integer DIV >> MUL >= ADD. 9// We MEASURE it here -- the relative costs become the optimizer's cost table. 10// Known answer (FAIL LOUD on the ordering, not exact cycles which vary): exit 0 11// iff measured div_cost > mul_cost AND mul_cost >= add_cost. 12 13import "nx_syscalls.nx" 14 15const MC_ITERS: i64 = 2000000 16 17// time a tight loop of ADDs; returns cycles. acc is fed back + consumed so the 18// op cannot be optimized away. 19func mc_time_add(seed: i64) -> i64 { 20 let t0: i64 = __rdtsc() 21 var acc: i64 = seed 22 var i: i64 = 0 23 while i < MC_ITERS { acc = acc + i; i = i + 1 } 24 let t1: i64 = __rdtsc() 25 if acc == 0 - 1 { sys_write(1, "" as *u8, 0) } // consume acc 26 return t1 - t0 27} 28func mc_time_mul(seed: i64) -> i64 { 29 let t0: i64 = __rdtsc() 30 var acc: i64 = seed | 1 31 var i: i64 = 0 32 while i < MC_ITERS { acc = acc * 3; acc = acc | 1; i = i + 1 } 33 let t1: i64 = __rdtsc() 34 if acc == 0 - 1 { sys_write(1, "" as *u8, 0) } 35 return t1 - t0 36} 37func mc_time_div(seed: i64) -> i64 { 38 let t0: i64 = __rdtsc() 39 var acc: i64 = 1000000007 40 var i: i64 = 0 41 while i < MC_ITERS { acc = acc / 3; acc = acc + 1000000007; i = i + 1 } 42 let t1: i64 = __rdtsc() 43 if acc == 0 - 1 { sys_write(1, "" as *u8, 0) } 44 return t1 - t0 45} 46 47func _emit(name: *u8, v: i64) -> i64 { 48 var n: i64 = 0; while name[n] != (0 as u8) { n = n + 1 } sys_write(1, name, n) 49 let b: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m } 50 let t: *u8 = sys_mmap(28); var k: i64 = 0 51 if m == 0 { t[0] = 48; k = 1 } 52 while m > 0 { t[k] = 48 + (m % 10); m = m / 10; k = k + 1 } 53 var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 } 54 b[k] = 10; sys_write(1, b, k + 1); return 0 55} 56 57func main() -> i64 { 58 // warm up, then measure (best-of-3 to reduce scheduler noise). 59 var ca: i64 = mc_time_add(7) 60 var cm: i64 = mc_time_mul(7) 61 var cd: i64 = mc_time_div(7) 62 var r: i64 = 0 63 while r < 2 { 64 let a2: i64 = mc_time_add(7); if a2 < ca { ca = a2 } 65 let m2: i64 = mc_time_mul(7); if m2 < cm { cm = m2 } 66 let d2: i64 = mc_time_div(7); if d2 < cd { cd = d2 } 67 r = r + 1 68 } 69 70 sys_write(1, "MEASURED hardware cost (cycles for " as *u8, 35) 71 _emit(" iters):" as *u8, MC_ITERS) 72 _emit(" ADD = " as *u8, ca) 73 _emit(" MUL = " as *u8, cm) 74 _emit(" DIV = " as *u8, cd) 75 // normalized to ADD (the optimizer's measured cost table) 76 if ca > 0 { 77 _emit(" rel MUL/ADD x100 = " as *u8, (cm * 100) / ca) 78 _emit(" rel DIV/ADD x100 = " as *u8, (cd * 100) / ca) 79 } 80 81 // FAIL LOUD on the reality ordering (cycles vary; the ORDER is universal). 82 if cd <= cm { sys_exit(1); return 1 } // div must be the slowest -> route around it 83 if cm < ca { sys_exit(2); return 2 } // mul at least as costly as add 84 sys_exit(0); return 0 85}