pub fn apply_attn_res(
prefix_sum: &[f32],
block_residual: &[f32],
norm_weight: &[f32],
proj_weight: &[f32],
eps: f32,
) -> Vec<f32> {
let score_weight: Vec<f32> = norm_weight
.iter()
.zip(proj_weight.iter())
.map(|(n, p)| n * p)
.collect();
apply_attn_res_prescored(prefix_sum, block_residual, &score_weight, eps)
}
pub fn apply_attn_res_prescored(
prefix_sum: &[f32],
block_residual: &[f32],
score_weight: &[f32],
eps: f32,
) -> Vec<f32> {
let hidden_dim = prefix_sum.len();
assert_eq!(score_weight.len(), hidden_dim);
assert!(block_residual.len().is_multiple_of(hidden_dim));
let n_blocks = block_residual.len() / hidden_dim;
let n_candidates = n_blocks + 1;
let candidate = |c: usize| -> &[f32] {
if c < n_blocks {
&block_residual[c * hidden_dim..(c + 1) * hidden_dim]
} else {
prefix_sum
}
};
let mut scores = vec![0f32; n_candidates];
for (c, score) in scores.iter_mut().enumerate() {
let v = candidate(c);
let mean_sq: f32 = v.iter().map(|x| x * x).sum::<f32>() / hidden_dim as f32;
let rstd = 1.0 / (mean_sq + eps).sqrt();
*score = v
.iter()
.zip(score_weight.iter())
.map(|(x, w)| (x * rstd) * w)
.sum();
}
let max = scores.iter().cloned().fold(f32::NEG_INFINITY, f32::max);
let mut probs = vec![0f32; n_candidates];
let mut sum = 0f32;
for (c, p) in probs.iter_mut().enumerate() {
*p = (scores[c] - max).exp();
sum += *p;
}
for p in probs.iter_mut() {
*p /= sum;
}
let mut out = vec![0f32; hidden_dim];
for (c, &w) in probs.iter().enumerate() {
let v = candidate(c);
for (o, x) in out.iter_mut().zip(v.iter()) {
*o += w * x;
}
}
out
}
#[cfg(test)]
mod tests {
use super::*;
const PREFIX_SUM: [f32; 4] = [0.00123015, 0.298746, -0.274138, -0.890592];
const BLOCK_RESIDUAL: [f32; 8] = [
-0.454671, -0.991647, 0.0601436, 1.34022, -0.492207, -0.620475, 0.489842, 0.356887,
];
const NORM_WEIGHT: [f32; 4] = [1.01054, 0.906953, 0.997075, 1.06953];
const PROJ_WEIGHT: [f32; 4] = [-1.34421, -0.457616, -1.90122, -1.28954];
const EXPECTED: [f32; 4] = [-0.0107297, 0.271161, -0.26009, -0.847388];
#[test]
fn matches_independent_python_reference() {
let got = apply_attn_res(
&PREFIX_SUM,
&BLOCK_RESIDUAL,
&NORM_WEIGHT,
&PROJ_WEIGHT,
1e-5,
);
for (i, (a, b)) in got.iter().zip(EXPECTED.iter()).enumerate() {
assert!((a - b).abs() < 1e-4, "element {i}: rust={a} python={b}");
}
}
#[test]
fn with_no_saved_checkpoints_softmax_over_one_candidate_is_the_identity() {
let prefix_sum = [1.0f32, -2.0, 3.5];
let norm_weight = [0.7f32, 1.3, -0.2];
let proj_weight = [2.0f32, -1.0, 0.5];
let got = apply_attn_res(&prefix_sum, &[], &norm_weight, &proj_weight, 1e-5);
for (a, b) in got.iter().zip(prefix_sum.iter()) {
assert!((a - b).abs() < 1e-5);
}
}
}