#[test]
fn test_imp_044_parallel_ffn() {
use crate::gpu::{parallel_ffn, sequential_ffn};
use std::time::Instant;
let hidden_dim = 256;
let intermediate_dim = 512;
let w_up: Vec<f32> = (0..hidden_dim * intermediate_dim)
.map(|i| ((i % 100) as f32) * 0.01 - 0.5)
.collect();
let w_down: Vec<f32> = (0..intermediate_dim * hidden_dim)
.map(|i| ((i % 100) as f32) * 0.01 - 0.5)
.collect();
let input: Vec<f32> = (0..hidden_dim).map(|i| (i as f32) * 0.01).collect();
let sequential_result = sequential_ffn(&input, &w_up, &w_down, hidden_dim, intermediate_dim);
let parallel_result = parallel_ffn(&input, &w_up, &w_down, hidden_dim, intermediate_dim);
assert_eq!(
sequential_result.len(),
parallel_result.len(),
"IMP-044: Results should have same length"
);
for (i, (&s, &p)) in sequential_result
.iter()
.zip(parallel_result.iter())
.enumerate()
{
assert!(
(s - p).abs() < 1e-4,
"IMP-044: Mismatch at index {}: sequential={}, parallel={}",
i,
s,
p
);
}
let large_input: Vec<f32> = (0..hidden_dim).map(|i| (i as f32) * 0.01).collect();
for _ in 0..3 {
let _ = sequential_ffn(&large_input, &w_up, &w_down, hidden_dim, intermediate_dim);
let _ = parallel_ffn(&large_input, &w_up, &w_down, hidden_dim, intermediate_dim);
}
let mut seq_times = Vec::with_capacity(5);
for _ in 0..5 {
let start = Instant::now();
for _ in 0..50 {
let _ = sequential_ffn(&large_input, &w_up, &w_down, hidden_dim, intermediate_dim);
}
seq_times.push(start.elapsed().as_secs_f64());
}
seq_times.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
let mut par_times = Vec::with_capacity(5);
for _ in 0..5 {
let start = Instant::now();
for _ in 0..50 {
let _ = parallel_ffn(&large_input, &w_up, &w_down, hidden_dim, intermediate_dim);
}
par_times.push(start.elapsed().as_secs_f64());
}
par_times.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
let seq_median = seq_times[seq_times.len() / 2];
let par_median = par_times[par_times.len() / 2];
let speedup = seq_median / par_median;
let _ = speedup; }
#[test]
fn test_imp_045_optimized_layernorm() {
use crate::gpu::{fused_layernorm, standard_layernorm};
use std::time::Instant;
let hidden_dim = 256;
let eps = 1e-5;
let input: Vec<f32> = (0..hidden_dim).map(|i| (i as f32) * 0.1 - 12.8).collect();
let gamma: Vec<f32> = vec![1.0; hidden_dim];
let beta: Vec<f32> = vec![0.0; hidden_dim];
let standard_result = standard_layernorm(&input, &gamma, &beta, eps);
let fused_result = fused_layernorm(&input, &gamma, &beta, eps);
assert_eq!(
standard_result.len(),
fused_result.len(),
"IMP-045: Results should have same length"
);
for (i, (&s, &f)) in standard_result.iter().zip(fused_result.iter()).enumerate() {
assert!(
(s - f).abs() < 1e-5,
"IMP-045: Mismatch at index {}: standard={}, fused={}",
i,
s,
f
);
}
let mean: f32 = fused_result.iter().sum::<f32>() / fused_result.len() as f32;
assert!(
mean.abs() < 0.1,
"IMP-045: Normalized output mean ({}) should be near 0",
mean
);
for _ in 0..5 {
let _ = standard_layernorm(&input, &gamma, &beta, eps);
let _ = fused_layernorm(&input, &gamma, &beta, eps);
}
let mut std_times = Vec::with_capacity(10);
for _ in 0..10 {
let start = Instant::now();
for _ in 0..100 {
let _ = standard_layernorm(&input, &gamma, &beta, eps);
}
std_times.push(start.elapsed().as_secs_f64());
}
std_times.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
let mut fused_times = Vec::with_capacity(10);
for _ in 0..10 {
let start = Instant::now();
for _ in 0..100 {
let _ = fused_layernorm(&input, &gamma, &beta, eps);
}
fused_times.push(start.elapsed().as_secs_f64());
}
fused_times.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
let std_median = std_times[std_times.len() / 2];
let fused_median = fused_times[fused_times.len() / 2];
let speedup = std_median / fused_median;
let _ = speedup;
}