code wiki / _hdl_build / nx_nofloat_kda_gate.nx

nx_nofloat_kda_gate.nx source

↩ module page · 147 lines · 7018 B

1// nx_nofloat_kda_gate.nx -- gate: Kimi Delta Attention, the K3-distinctive behaviors (not just "it runs"). 2// T1 DELTA OVERWRITE: writing the SAME key twice (v1 then v2) OVERWRITES to v2 -- vs plain linear-attn 3// which superposes to v1+v2. This is the delta-rule signature (key-value memory, not accumulation). 4// T2 CHANNEL GATING DECAY: a stored value decays monotonically under repeated per-channel gating (alpha<1). 5// T3 GATE=1 PERSISTENCE: with alpha=1 and no write, the memory is bit-identical across steps (stable). 6// T4 DETERMINISTIC: kda_forward twice = bit-identical (the exceed: float delta/gated stacks drift). 7// T5 FINE-GRAINED (per-channel): two key-channels with DIFFERENT alpha decay at different rates -> the 8// cross-channel magnitude RATIO changes (scalar/GLA gating would preserve it). The KDA-vs-GLA distinction. 9// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 10import "nx_nofloat_kda.nx" 11import "nx_nofloat_linattn.nx" 12import "nx_gate_verdict.nx" 13import "nx_syscalls.nx" 14 15const KG_Q: i64 = 65536 16const KG_D: i64 = 4 17 18func kg_abs(x: i64) -> i64 { if x < 0 { return 0 - x } return x } 19 20func main() -> i64 { 21 let ctr: *i64 = gv_ctr() 22 gv_head("nx_nofloat_kda gate -- Kimi Delta Attention: delta-overwrite + per-channel gating, deterministic" as *u8) 23 let d: i64 = KG_D 24 let Q: i64 = KG_Q 25 26 // one-hot unit key e0 = [1,0,0,0] (k.k = 1.0), and value vectors 27 let e0: *i64 = sys_mmap(16*8) as *i64 28 let ones: *i64 = sys_mmap(16*8) as *i64 29 let v1: *i64 = sys_mmap(16*8) as *i64 30 let v2: *i64 = sys_mmap(16*8) as *i64 31 var i: i64 = 0 32 while i < d { e0[i] = 0; ones[i] = Q; v1[i] = Q/2; v2[i] = (Q*3)/10; i = i + 1 } 33 e0[0] = Q 34 let pred: *i64 = sys_mmap(16*8) as *i64 35 let delta: *i64 = sys_mmap(16*8) as *i64 36 37 // ---- T1: delta OVERWRITE vs plain SUPERPOSE ---- 38 let sk: *i64 = sys_mmap(LA_DMAX*LA_DMAX*8) as *i64 39 let sp: *i64 = sys_mmap(LA_DMAX*LA_DMAX*8) as *i64 40 la_zero(sk, d); la_zero(sp, d) 41 // KDA: two delta-writes of the same key, no gating (alpha=1, beta=1) 42 kda_write(sk, e0, v1, Q, d, pred, delta) 43 kda_write(sk, e0, v2, Q, d, pred, delta) 44 let okda: *i64 = sys_mmap(16*8) as *i64 45 la_readout(sk, e0, okda, d) 46 // plain linear-attn: two accums of the same key 47 la_accum(sp, e0, v1, d) 48 la_accum(sp, e0, v2, d) 49 let oplain: *i64 = sys_mmap(16*8) as *i64 50 la_readout(sp, e0, oplain, d) 51 // assert: kda ~ v2 (overwrite), plain ~ v1+v2 (superpose), and they DIFFER 52 var t1: i64 = 1 53 let eps: i64 = Q/100 54 i = 0 55 while i < d { 56 if kg_abs(okda[i] - v2[i]) > eps { t1 = 0 } 57 if kg_abs(oplain[i] - (v1[i]+v2[i])) > eps { t1 = 0 } 58 if kg_abs(okda[i] - oplain[i]) < eps { t1 = 0 } 59 i = i + 1 60 } 61 gv_check("T1 DELTA-RULE OVERWRITE: same-key rewrite -> v2 (kda) vs v1+v2 (plain linattn)" as *u8, t1, ctr) 62 63 // ---- T2: per-channel gating decays a stored value monotonically ---- 64 let s2: *i64 = sys_mmap(LA_DMAX*LA_DMAX*8) as *i64 65 let ahalf: *i64 = sys_mmap(16*8) as *i64 66 i = 0 67 while i < d { ahalf[i] = Q/2; i = i + 1 } 68 la_zero(s2, d) 69 kda_write(s2, e0, v1, Q, d, pred, delta) // store v1 along e0 70 let o2: *i64 = sys_mmap(16*8) as *i64 71 la_readout(s2, e0, o2, d) 72 let m0: i64 = kg_abs(o2[0]) 73 kda_gate(s2, ahalf, d); la_readout(s2, e0, o2, d); let m1: i64 = kg_abs(o2[0]) 74 kda_gate(s2, ahalf, d); la_readout(s2, e0, o2, d); let m2: i64 = kg_abs(o2[0]) 75 kda_gate(s2, ahalf, d); la_readout(s2, e0, o2, d); let m3: i64 = kg_abs(o2[0]) 76 var t2: i64 = 0 77 if m1 < m0 { if m2 < m1 { if m3 < m2 { if m0 > 0 { t2 = 1 } } } } 78 gv_check("T2 CHANNEL GATING DECAY: stored value shrinks monotonically under alpha<1" as *u8, t2, ctr) 79 80 // ---- T3: alpha=1 + no write -> memory bit-identical across steps ---- 81 let s3: *i64 = sys_mmap(LA_DMAX*LA_DMAX*8) as *i64 82 la_zero(s3, d) 83 kda_write(s3, e0, v1, Q, d, pred, delta) 84 let o3a: *i64 = sys_mmap(16*8) as *i64 85 let o3b: *i64 = sys_mmap(16*8) as *i64 86 la_readout(s3, e0, o3a, d) 87 kda_gate(s3, ones, d); kda_gate(s3, ones, d); kda_gate(s3, ones, d) 88 la_readout(s3, e0, o3b, d) 89 var t3: i64 = 1 90 i = 0 91 while i < d { if o3a[i] != o3b[i] { t3 = 0 } i = i + 1 } 92 gv_check("T3 GATE=1 PERSISTENCE: memory bit-identical across empty gated steps" as *u8, t3, ctr) 93 94 // ---- T4: deterministic forward ---- 95 let t: i64 = 4 96 let qm: *i64 = sys_mmap(64*8) as *i64 97 let km: *i64 = sys_mmap(64*8) as *i64 98 let vm: *i64 = sys_mmap(64*8) as *i64 99 let oA: *i64 = sys_mmap(64*8) as *i64 100 let oB: *i64 = sys_mmap(64*8) as *i64 101 i = 0 102 while i < t*d { qm[i] = ((i%3)+1)*(Q/8); km[i] = ((i%4)+1)*(Q/10); vm[i] = ((i%5)+1)*(Q/12); i = i + 1 } 103 kda_forward(qm, km, vm, oA, ahalf, Q, t, d) 104 kda_forward(qm, km, vm, oB, ahalf, Q, t, d) 105 var t4: i64 = 1 106 i = 0 107 while i < t*d { if oA[i] != oB[i] { t4 = 0 } i = i + 1 } 108 gv_check("T4 DETERMINISTIC bit-identical forward (float delta/gated stacks drift)" as *u8, t4, ctr) 109 110 // ---- T5: fine-grained per-channel gating changes the cross-channel ratio ---- 111 // key with mass in rows 0 AND 1 (0.707,0.707): store v, then gate rows at DIFFERENT rates. 112 let ktwo: *i64 = sys_mmap(16*8) as *i64 113 i = 0 114 while i < d { ktwo[i] = 0; i = i + 1 } 115 ktwo[0] = 46341; ktwo[1] = 46341 // ~1/sqrt2 each (unit key) 116 let adiff: *i64 = sys_mmap(16*8) as *i64 117 i = 0 118 while i < d { adiff[i] = Q; i = i + 1 } 119 adiff[0] = Q/2; adiff[1] = Q/4 // row0 halves, row1 quarters -> differential 120 let s5: *i64 = sys_mmap(LA_DMAX*LA_DMAX*8) as *i64 121 la_zero(s5, d) 122 kda_write(s5, ktwo, v1, Q, d, pred, delta) 123 // pick row0 via e0, row1 via e1 124 let e1: *i64 = sys_mmap(16*8) as *i64 125 i = 0 126 while i < d { e1[i] = 0; i = i + 1 } 127 e1[1] = Q 128 let r0: *i64 = sys_mmap(16*8) as *i64 129 let r1: *i64 = sys_mmap(16*8) as *i64 130 la_readout(s5, e0, r0, d); la_readout(s5, e1, r1, d) 131 let a0: i64 = kg_abs(r0[0]); let b0: i64 = kg_abs(r1[0]) // magnitudes before gating (ratio ~1) 132 kda_gate(s5, adiff, d); kda_gate(s5, adiff, d) // two differential gated steps 133 la_readout(s5, e0, r0, d); la_readout(s5, e1, r1, d) 134 let a1: i64 = kg_abs(r0[0]); let b1: i64 = kg_abs(r1[0]) // after: row1 decayed faster 135 // ratio b/a: before ~1, after should DROP (row1 quartered^2 vs row0 halved^2). scale by Q to compare. 136 var t5: i64 = 0 137 if a0 > 0 { if a1 > 0 { 138 let ratio_before: i64 = (b0 * Q) / a0 139 let ratio_after: i64 = (b1 * Q) / a1 140 if ratio_after < ratio_before { t5 = 1 } 141 } } 142 gv_check("T5 FINE-GRAINED per-channel gating: cross-channel ratio shifts (KDA-vs-GLA distinction)" as *u8, t5, ctr) 143 144 let rc: i64 = gv_verdict("NOFLOAT-KDA-GATE" as *u8, ctr, "Kimi Delta Attention: delta-overwrite memory + per-channel diagonal gating, bit-exact deterministic no-float" as *u8) 145 sys_exit(rc) 146 return rc 147}