metrale_model_arch/glm5next_dsa_ref/
mla.rs1use super::*;
9
10pub fn mla_masked_attention(
18 q: &[f32],
19 k: &[f32],
20 v: &[f32],
21 mask: &[u8],
22 dims: DsaDims,
23 q_rows: usize,
24 kv_len: usize,
25) -> Vec<f32> {
26 let (h, qd, vd) = (dims.heads, dims.qk_head_dim(), dims.v_head_dim);
27 let scale = (qd as f32).powf(-0.5);
28 let mut out = vec![0.0f32; q_rows * h * vd];
29 for r in 0..q_rows {
30 for hh in 0..h {
31 let mut m = f32::NEG_INFINITY;
33 let mut l = 0.0f32;
34 let mut acc = vec![0.0f32; vd];
35 for kk in 0..kv_len {
36 if mask[r * kv_len + kk] == 0 {
37 continue;
38 }
39 let mut dot = 0.0f32;
40 for dd in 0..qd {
41 dot += q[(r * h + hh) * qd + dd] * k[(kk * h + hh) * qd + dd];
42 }
43 let s = dot * scale;
44 let m_new = m.max(s);
45 let corr = if m == f32::NEG_INFINITY {
46 0.0
47 } else {
48 (m - m_new).exp()
49 };
50 let p = (s - m_new).exp();
51 l = l * corr + p;
52 for dd in 0..vd {
53 acc[dd] = acc[dd] * corr + p * v[(kk * h + hh) * vd + dd];
54 }
55 m = m_new;
56 }
57 let inv = if l > 0.0 { 1.0 / l } else { 0.0 };
58 for dd in 0..vd {
59 out[(r * h + hh) * vd + dd] = acc[dd] * inv;
60 }
61 }
62 }
63 out
64}
65
66pub fn expand_kv(kv_c: &[f32], w_kv_b: &[f32], dims: DsaDims, seq: usize) -> (Vec<f32>, Vec<f32>) {
69 let (h, nope, vd, r) = (
70 dims.heads,
71 dims.qk_nope_head_dim,
72 dims.v_head_dim,
73 dims.kv_lora_rank,
74 );
75 assert_eq!(dims.qk_rope_head_dim, 0, "expand_kv is the NoPE path");
76 let wide = linear(kv_c, seq, r, w_kv_b, h * (nope + vd));
77 let mut k = vec![0.0f32; seq * h * nope];
78 let mut v = vec![0.0f32; seq * h * vd];
79 for t in 0..seq {
80 for hh in 0..h {
81 let src = t * h * (nope + vd) + hh * (nope + vd);
82 k[(t * h + hh) * nope..(t * h + hh) * nope + nope]
83 .copy_from_slice(&wide[src..src + nope]);
84 v[(t * h + hh) * vd..(t * h + hh) * vd + vd]
85 .copy_from_slice(&wide[src + nope..src + nope + vd]);
86 }
87 }
88 (k, v)
89}