metrale_model_arch/glm5next_dsa_ref/
mod.rs1#[derive(Clone, Copy, Debug)]
27pub struct DsaDims {
28 pub hidden: usize,
29 pub index_heads: usize,
31 pub index_head_dim: usize,
33 pub index_kpool: usize,
34 pub index_topk: usize,
35 pub always_select_tail: bool,
36 pub q_lora_rank: usize,
37 pub heads: usize,
38 pub kv_lora_rank: usize,
39 pub qk_nope_head_dim: usize,
40 pub qk_rope_head_dim: usize,
42 pub v_head_dim: usize,
43}
44
45impl DsaDims {
46 pub fn qk_head_dim(&self) -> usize {
47 self.qk_nope_head_dim + self.qk_rope_head_dim
48 }
49 pub fn select_k(&self, n_pools: usize) -> usize {
52 (self.index_topk / self.index_kpool).min(n_pools)
53 }
54 pub fn out_width(&self) -> usize {
56 self.index_topk
57 + if self.always_select_tail {
58 self.index_kpool - 1
59 } else {
60 0
61 }
62 }
63 pub fn is_nope(&self) -> bool {
64 self.qk_rope_head_dim == 0
65 }
66}
67
68pub const INVALID: i32 = -1;
70
71#[inline]
72fn sigmoid(x: f32) -> f32 {
73 1.0 / (1.0 + (-x).exp())
74}
75
76pub fn layer_norm(x: &[f32], w: &[f32], b: &[f32], d: usize, eps: f32) -> Vec<f32> {
79 let mut out = vec![0.0f32; x.len()];
80 for (row_in, row_out) in x.chunks_exact(d).zip(out.chunks_exact_mut(d)) {
81 let mean = row_in.iter().sum::<f32>() / d as f32;
82 let var = row_in.iter().map(|v| (v - mean) * (v - mean)).sum::<f32>() / d as f32;
83 let inv = 1.0 / (var + eps).sqrt();
84 for i in 0..d {
85 row_out[i] = (row_in[i] - mean) * inv * w[i] + b[i];
86 }
87 }
88 out
89}
90
91pub fn rms_norm(x: &[f32], w: &[f32], d: usize, eps: f32) -> Vec<f32> {
93 let mut out = vec![0.0f32; x.len()];
94 for (row_in, row_out) in x.chunks_exact(d).zip(out.chunks_exact_mut(d)) {
95 let inv = 1.0 / (row_in.iter().map(|v| v * v).sum::<f32>() / d as f32 + eps).sqrt();
96 for i in 0..d {
97 row_out[i] = row_in[i] * inv * w[i];
98 }
99 }
100 out
101}
102
103pub fn linear(x: &[f32], m: usize, k: usize, w: &[f32], n: usize) -> Vec<f32> {
105 let mut out = vec![0.0f32; m * n];
106 for row in 0..m {
107 for col in 0..n {
108 let mut acc = 0.0f32;
109 for i in 0..k {
110 acc += x[row * k + i] * w[col * k + i];
111 }
112 out[row * n + col] = acc;
113 }
114 }
115 out
116}
117
118pub struct Pools {
120 pub keys: Vec<f32>,
122 pub indices: Vec<i32>,
125 pub valid: Vec<u8>,
127 pub n_pools: usize,
128}
129
130pub fn pool_states(
133 k: &[f32],
134 gate: &[f32],
135 valid: &[u8],
136 ape: &[f32],
137 dims: DsaDims,
138 seq: usize,
139) -> Pools {
140 let (d, kp) = (dims.index_head_dim, dims.index_kpool);
141 let n_pools = seq.div_ceil(kp);
142 let first_key = valid.iter().position(|v| *v != 0).unwrap_or(seq) as i64;
144
145 let mut keys = vec![0.0f32; n_pools * d];
146 let mut indices = vec![INVALID; n_pools * kp];
147 let mut pvalid = vec![0u8; n_pools];
148 let mut logits = vec![0.0f32; kp];
149
150 for p in 0..n_pools {
151 let mut slot_valid = [false; 64];
152 let mut slot_idx = [0usize; 64];
153 let mut all = true;
154 for s in 0..kp {
155 let raw = first_key + (p * kp + s) as i64;
156 let in_range = raw >= 0 && (raw as usize) < seq;
157 let ok = in_range && valid[raw as usize] != 0;
158 slot_valid[s] = ok;
159 slot_idx[s] = if in_range { raw as usize } else { 0 };
160 all &= ok;
161 indices[p * kp + s] = if ok { raw as i32 } else { INVALID };
162 }
163 pvalid[p] = all as u8;
164
165 for dd in 0..d {
167 let mut mx = f32::NEG_INFINITY;
168 for s in 0..kp {
169 logits[s] = if slot_valid[s] {
170 gate[slot_idx[s] * d + dd] + ape[s * d + dd]
171 } else {
172 f32::NEG_INFINITY
173 };
174 mx = mx.max(logits[s]);
175 }
176 let mut sum = 0.0f32;
177 for s in 0..kp {
178 let e = if logits[s] == f32::NEG_INFINITY {
179 0.0
180 } else {
181 (logits[s] - mx).exp()
182 };
183 logits[s] = e;
184 sum += e;
185 }
186 let inv = if sum > 0.0 { 1.0 / sum } else { 0.0 };
188 let mut acc = 0.0f32;
189 for s in 0..kp {
190 if slot_valid[s] {
191 acc += logits[s] * inv * k[slot_idx[s] * d + dd];
192 }
193 }
194 keys[p * d + dd] = acc;
195 }
196 }
197 let keep: Vec<usize> = (0..n_pools).filter(|p| pvalid[*p] != 0).collect();
201 if keep.len() == n_pools {
202 return Pools {
203 keys,
204 indices,
205 valid: pvalid,
206 n_pools,
207 };
208 }
209 let mut ck = vec![0.0f32; keep.len() * d];
210 let mut ci = vec![INVALID; keep.len() * kp];
211 let mut cv = vec![0u8; keep.len()];
212 for (j, p) in keep.iter().enumerate() {
213 ck[j * d..(j + 1) * d].copy_from_slice(&keys[p * d..(p + 1) * d]);
214 ci[j * kp..(j + 1) * kp].copy_from_slice(&indices[p * kp..(p + 1) * kp]);
215 cv[j] = pvalid[*p];
216 }
217 Pools {
218 keys: ck,
219 indices: ci,
220 valid: cv,
221 n_pools: keep.len(),
222 }
223}
224
225pub fn kept_pools(valid: &[u8], dims: DsaDims, seq: usize) -> Vec<i32> {
228 let kp = dims.index_kpool;
229 let n_pools = seq.div_ceil(kp);
230 let first_key = valid.iter().position(|v| *v != 0).unwrap_or(seq) as i64;
231 (0..n_pools)
232 .filter(|p| {
233 (0..kp).all(|s| {
234 let raw = first_key + (p * kp + s) as i64;
235 raw >= 0 && (raw as usize) < seq && valid[raw as usize] != 0
236 })
237 })
238 .map(|p| p as i32)
239 .collect()
240}
241
242pub fn index_scores(
247 q: &[f32],
248 weights: &[f32],
249 pools: &Pools,
250 dims: DsaDims,
251 q_rows: usize,
252) -> Vec<f32> {
253 let (h, d, p) = (dims.index_heads, dims.index_head_dim, pools.n_pools);
254 let scale = (d as f32).powf(-0.5);
255 let mut out = vec![0.0f32; q_rows * p];
256 for r in 0..q_rows {
257 for pp in 0..p {
258 let mut acc = 0.0f32;
259 for hh in 0..h {
260 let mut dot = 0.0f32;
261 for dd in 0..d {
262 dot += q[(r * h + hh) * d + dd] * pools.keys[pp * d + dd];
263 }
264 acc += weights[r * h + hh] * (scale * dot).max(0.0);
267 }
268 out[r * p + pp] = acc;
269 }
270 }
271 out
272}
273
274pub fn visible(valid_keys: &[u8], q_pos: usize, key_idx: usize) -> bool {
276 key_idx <= q_pos && valid_keys[key_idx] != 0
277}
278
279pub fn topk_pools(
282 scores: &[f32],
283 valid_candidates: &[u8],
284 n_pools: usize,
285 q_rows: usize,
286 select_k: usize,
287) -> Vec<i32> {
288 let mut out = vec![INVALID; q_rows * select_k];
289 let mut buf: Vec<(f32, usize)> = Vec::with_capacity(n_pools);
290 for r in 0..q_rows {
291 buf.clear();
292 for p in 0..n_pools {
293 let s = if valid_candidates[r * n_pools + p] != 0 {
294 scores[r * n_pools + p]
295 } else {
296 f32::MIN
297 };
298 buf.push((s, p));
299 }
300 buf.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap().then(a.1.cmp(&b.1)));
301 for (j, (_, p)) in buf.iter().take(select_k).enumerate() {
302 out[r * select_k + j] = *p as i32;
303 }
304 }
305 out
306}
307
308#[allow(clippy::too_many_arguments)]
312pub fn expand_selection(
313 selected: &[i32],
314 pools: &Pools,
315 valid_candidates: &[u8],
316 valid_keys: &[u8],
317 q_positions: &[usize],
318 q_mask: &[u8],
319 dims: DsaDims,
320 seq: usize,
321 select_k: usize,
322) -> Vec<i32> {
323 let (kp, width) = (dims.index_kpool, dims.out_width());
324 let q_rows = q_positions.len();
325 let mut out = vec![INVALID; q_rows * width];
326
327 let first_key = valid_keys.iter().position(|v| *v != 0).unwrap_or(seq) as i64;
328 for r in 0..q_rows {
329 let row = &mut out[r * width..(r + 1) * width];
330 if q_mask[r] == 0 {
331 continue;
332 }
333 let mut w = 0usize;
334 for j in 0..select_k {
335 let p = selected[r * select_k + j];
336 let ok = p >= 0 && valid_candidates[r * pools.n_pools + p as usize] != 0;
337 for s in 0..kp {
338 row[w] = if ok {
339 pools.indices[p as usize * kp + s]
340 } else {
341 INVALID
342 };
343 w += 1;
344 }
345 }
346 if dims.always_select_tail {
347 let vis_count = (0..seq)
349 .filter(|k| visible(valid_keys, q_positions[r], *k))
350 .count();
351 let tail_count = vis_count % kp;
352 let tail_start = first_key + vis_count as i64 - tail_count as i64;
353 for t in 0..kp - 1 {
354 let idx = tail_start + t as i64;
355 let ok = t < tail_count
356 && idx >= 0
357 && (idx as usize) < seq
358 && visible(valid_keys, q_positions[r], idx as usize);
359 row[w] = if ok { idx as i32 } else { INVALID };
360 w += 1;
361 }
362 }
363 debug_assert_eq!(
364 w,
365 width.min(select_k * kp + if dims.always_select_tail { kp - 1 } else { 0 })
366 );
367 }
368 out
369}
370
371pub fn topk_to_mask(topk: &[i32], q_rows: usize, width: usize, kv_len: usize) -> Vec<u8> {
375 let mut mask = vec![0u8; q_rows * kv_len];
376 for r in 0..q_rows {
377 for j in 0..width {
378 let i = topk[r * width + j];
379 if i >= 0 && (i as usize) < kv_len {
380 mask[r * kv_len + i as usize] = 1;
381 }
382 }
383 }
384 mask
385}
386
387pub fn sigmoid_f32(x: f32) -> f32 {
389 sigmoid(x)
390}
391
392mod mla;
393pub use mla::{expand_kv, mla_masked_attention};
394
395#[cfg(test)]
396mod tests;