code wiki / (root) / nx_f32_matmul.nx

nx_f32_matmul.nx source

↩ module page · 78 lines · 2543 B

1// nx_f32_matmul.nx -- bits-up f32 dot product + GEMM kernel. 2// 3// L7 composition brick. Last load-bearing math primitive for an 4// end-to-end f32-mode transformer block. Composes nx_f32_mul + 5// nx_f32_add over rows / columns. 6// 7// API: 8// nx_f32_dot(a, b, n) -- scalar dot product (sum of a[i]*b[i]) 9// nx_f32_matmul(a, b, c, m, k, n) 10// -- C[m,n] = A[m,k] @ B[k,n] 11// row-major storage 12// 13// Bit-exact when all operands and intermediate sums are 14// representable f32 (e.g., small ints). Otherwise round-to- 15// nearest-even accumulates per the L4 f32 ops. 16// 17// No libm. Inner MAC uses nx_f32_hw SSE intrinsics (__f32_add/__f32_mul -> real addss/mulss on the FPU), 18// which are BIT-EXACT vs the bits-up software f32 (proven by nx_f32_hw_matmul_gate's hw==sw differential) but 19// replace dozens of integer ops per multiply with one instruction -- the hardware rung the LLM forward stands on. 20import "nx_syscalls.nx" 21import "nx_tier.nx" 22import "nx_f32.nx" 23import "nx_f32_hw.nx" 24 25const NX_F32_MM_OK: nx_int = 0 26const NX_F32_MM_ERR_BAD_DIM: nx_int = 1 27const NX_F32_MM_N_VERDICTS: nx_int = 2 28 29func nx_f32_mm_verdict_is_valid(v: nx_int) -> nx_int { 30 if v < 0 { return 0 } 31 if v >= NX_F32_MM_N_VERDICTS { return 0 } 32 return 1 33} 34 35// Scalar dot product: sum_i a[i] * b[i], all f32 raw bits. 36 37func nx_f32_dot(a: *i64, b: *i64, n: nx_int) -> i64 { 38 var acc: i64 = 0 39 var i: nx_int = 0 40 while i < n { 41 acc = __f32_add(acc, __f32_mul(a[i], b[i])) 42 i = i + 1 43 } 44 return acc 45} 46 47// GEMM: C[m,n] = A[m,k] @ B[k,n], row-major. 48// 49// C[i,j] = sum_l A[i,l] * B[l,j] 50// 51// For typical LLM forward (single token), m=1, so the outer loop 52// runs once and this degenerates to k matrix-vector products. 53 54func nx_f32_matmul(a: *i64, b: *i64, c: *i64, 55 m: nx_int, k: nx_int, n: nx_int) -> nx_int { 56 if m <= 0 { return NX_F32_MM_ERR_BAD_DIM } 57 if k <= 0 { return NX_F32_MM_ERR_BAD_DIM } 58 if n <= 0 { return NX_F32_MM_ERR_BAD_DIM } 59 60 var i: nx_int = 0 61 while i < m { 62 var j: nx_int = 0 63 while j < n { 64 var acc: i64 = 0 65 var l: nx_int = 0 66 while l < k { 67 let a_il: i64 = a[i * k + l] 68 let b_lj: i64 = b[l * n + j] 69 acc = __f32_add(acc, __f32_mul(a_il, b_lj)) 70 l = l + 1 71 } 72 c[i * n + j] = acc 73 j = j + 1 74 } 75 i = i + 1 76 } 77 return NX_F32_MM_OK 78}