use crate::gpu::scheduler::batch::{
argmax, optimized_lm_head_argmax_transposed, simplified_attention,
};
use crate::gpu::scheduler::GpuModelConfig;
#[test]
fn test_argmax_empty_input() {
let logits: Vec<f32> = vec![];
let result = argmax(&logits);
assert_eq!(result, 0, "Empty input should return 0");
}
#[test]
fn test_argmax_single_element() {
let logits = vec![42.0];
let result = argmax(&logits);
assert_eq!(result, 0, "Single element should return index 0");
}
#[test]
fn test_argmax_small_vocab_first_max() {
let logits = vec![10.0, 5.0, 3.0, 1.0];
let result = argmax(&logits);
assert_eq!(result, 0, "First element is max");
}
#[test]
fn test_argmax_small_vocab_last_max() {
let logits = vec![1.0, 2.0, 3.0, 100.0];
let result = argmax(&logits);
assert_eq!(result, 3, "Last element is max");
}
#[test]
fn test_argmax_small_vocab_middle_max() {
let logits = vec![1.0, 2.0, 100.0, 3.0, 4.0];
let result = argmax(&logits);
assert_eq!(result, 2, "Middle element is max");
}
#[test]
fn test_argmax_small_vocab_negative_values() {
let logits = vec![-10.0, -5.0, -1.0, -100.0];
let result = argmax(&logits);
assert_eq!(result, 2, "Largest negative is at index 2");
}
#[test]
fn test_argmax_small_vocab_all_equal() {
let logits = vec![5.0, 5.0, 5.0, 5.0];
let result = argmax(&logits);
assert!(result < logits.len(), "Index should be in bounds");
assert!(
(logits[result] - 5.0).abs() < 1e-6,
"Should point to a max value"
);
}
#[test]
fn test_argmax_small_vocab_infinity() {
let logits = vec![1.0, f32::INFINITY, 3.0, 4.0];
let result = argmax(&logits);
assert_eq!(result, 1, "Infinity should be max");
}
#[test]
fn test_argmax_small_vocab_neg_infinity() {
let logits = vec![f32::NEG_INFINITY, 1.0, 2.0, 3.0];
let result = argmax(&logits);
assert_eq!(result, 3, "Neg infinity should not be max");
}
#[test]
fn test_argmax_small_vocab_nan_handling() {
let logits = vec![1.0, f32::NAN, 3.0, 4.0];
let result = argmax(&logits);
assert!(result < logits.len());
}
#[test]
fn test_argmax_exactly_1024_elements() {
let mut logits = vec![0.0f32; 1024];
logits[500] = 100.0;
let result = argmax(&logits);
assert_eq!(result, 500);
}
#[test]
fn test_argmax_large_vocab_1025_elements() {
let mut logits = vec![0.0f32; 1025];
logits[1000] = 100.0;
let result = argmax(&logits);
assert_eq!(result, 1000);
}
#[test]
fn test_argmax_large_vocab_32k() {
let mut logits = vec![0.0f32; 32000];
logits[12345] = 100.0;
let result = argmax(&logits);
assert_eq!(result, 12345);
}
#[test]
fn test_argmax_large_vocab_65k() {
let mut logits = vec![0.0f32; 65536];
logits[65000] = 100.0;
let result = argmax(&logits);
assert_eq!(result, 65000);
}
#[test]
fn test_argmax_large_vocab_max_at_chunk_boundary() {
let mut logits = vec![0.0f32; 8192];
logits[4096] = 100.0;
let result = argmax(&logits);
assert_eq!(result, 4096);
}
#[test]
fn test_argmax_large_vocab_max_in_last_chunk() {
let mut logits = vec![0.0f32; 5000];
logits[4999] = 100.0;
let result = argmax(&logits);
assert_eq!(result, 4999);
}
#[test]
fn test_argmax_large_vocab_max_in_first_chunk() {
let mut logits = vec![0.0f32; 10000];
logits[100] = 100.0;
let result = argmax(&logits);
assert_eq!(result, 100);
}
#[test]
fn test_argmax_large_vocab_multiple_local_maxes() {
let mut logits = vec![0.0f32; 16384];
logits[1000] = 50.0; logits[5000] = 75.0; logits[9000] = 100.0; logits[13000] = 60.0; let result = argmax(&logits);
assert_eq!(result, 9000);
}
#[test]
fn test_optimized_lm_head_argmax_simple() {
let hidden = vec![1.0, 0.0, 0.0, 0.0];
let weight_t = vec![
1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, ];
let bias = vec![0.0, 0.0, 0.0, 0.0];
let result = optimized_lm_head_argmax_transposed(&hidden, &weight_t, &bias, 4, 4);
assert_eq!(result, 0);
}
#[test]
fn test_optimized_lm_head_argmax_with_bias() {
let hidden = vec![1.0, 0.0, 0.0, 0.0];
let weight_t = vec![
1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, ];
let bias = vec![0.0, 0.0, 10.0, 0.0];
let result = optimized_lm_head_argmax_transposed(&hidden, &weight_t, &bias, 4, 4);
assert_eq!(result, 2);
}
#[test]
fn test_optimized_lm_head_argmax_larger_vocab() {
let hidden_dim = 64;
let vocab_size = 5000;
let hidden: Vec<f32> = (0..hidden_dim).map(|i| (i as f32) * 0.01).collect();
let mut weight_t = vec![0.0f32; vocab_size * hidden_dim];
let bias = vec![0.0f32; vocab_size];
for i in 0..hidden_dim {
weight_t[2500 * hidden_dim + i] = hidden[i]; }
let result =
optimized_lm_head_argmax_transposed(&hidden, &weight_t, &bias, hidden_dim, vocab_size);
assert_eq!(result, 2500);
}
#[test]
fn test_optimized_lm_head_argmax_single_vocab() {
let hidden = vec![1.0, 2.0, 3.0, 4.0];
let weight_t = vec![1.0, 1.0, 1.0, 1.0]; let bias = vec![0.0];
let result = optimized_lm_head_argmax_transposed(&hidden, &weight_t, &bias, 4, 1);
assert_eq!(result, 0);
}
#[test]
fn test_optimized_lm_head_argmax_negative_logits() {
let hidden = vec![1.0, 1.0];
let weight_t = vec![
-1.0, -1.0, -0.5, -0.5, ];
let bias = vec![0.0, 0.0];
let result = optimized_lm_head_argmax_transposed(&hidden, &weight_t, &bias, 2, 2);
assert_eq!(result, 1);
}
#[test]
fn test_simplified_attention_single_token() {
let config = GpuModelConfig {
vocab_size: 100,
hidden_dim: 64,
num_heads: 4,
num_kv_heads: 4,
num_layers: 2,
intermediate_dim: 256,
eps: 1e-5,
rope_theta: 10000.0,
explicit_head_dim: None,
layer_types: None,
linear_key_head_dim: None,
linear_value_head_dim: None,
linear_num_key_heads: None,
linear_num_value_heads: None,
linear_conv_kernel_dim: None,
constraints: None,
num_experts: None,
num_experts_per_tok: None,
expert_intermediate_size: None,
};
let seq_len = 1;
let hidden_dim = config.hidden_dim;
let q = vec![1.0f32; hidden_dim];
let k = vec![1.0f32; hidden_dim];
let v = vec![2.0f32; hidden_dim];
let mut qkv = Vec::with_capacity(seq_len * 3 * hidden_dim);
qkv.extend(&q);
qkv.extend(&k);
qkv.extend(&v);
let result = simplified_attention(&config, &qkv, seq_len);
assert!(result.is_ok());
let output = result.expect("test value should be present");
assert_eq!(output.len(), hidden_dim);
for (i, &val) in output.iter().enumerate() {
assert!(
(val - v[i]).abs() < 1e-5,
"Output should equal V for single token"
);
}
}
#[test]
fn test_simplified_attention_two_tokens() {
let config = GpuModelConfig {
vocab_size: 100,
hidden_dim: 4, num_heads: 2,
num_kv_heads: 2,
num_layers: 2,
intermediate_dim: 16,
eps: 1e-5,
rope_theta: 10000.0,
explicit_head_dim: None,
layer_types: None,
linear_key_head_dim: None,
linear_value_head_dim: None,
linear_num_key_heads: None,
linear_num_value_heads: None,
linear_conv_kernel_dim: None,
constraints: None,
num_experts: None,
num_experts_per_tok: None,
expert_intermediate_size: None,
};
let seq_len = 2;
let hidden_dim = config.hidden_dim;
let q0 = vec![1.0f32; hidden_dim];
let q1 = vec![1.0f32; hidden_dim];
let k0 = vec![1.0f32; hidden_dim];
let k1 = vec![1.0f32; hidden_dim];
let v0 = vec![1.0f32; hidden_dim];
let v1 = vec![2.0f32; hidden_dim];
let mut qkv = Vec::with_capacity(seq_len * 3 * hidden_dim);
qkv.extend(&q0);
qkv.extend(&q1);
qkv.extend(&k0);
qkv.extend(&k1);
qkv.extend(&v0);
qkv.extend(&v1);
let result = simplified_attention(&config, &qkv, seq_len);
assert!(result.is_ok());
let output = result.expect("test value should be present");
assert_eq!(output.len(), seq_len * hidden_dim);
for i in 0..hidden_dim {
assert!(
(output[i] - v0[i]).abs() < 1e-5,
"Position 0 should only attend to itself"
);
}
for i in 0..hidden_dim {
let expected = 0.5 * v0[i] + 0.5 * v1[i];
assert!(
(output[hidden_dim + i] - expected).abs() < 1e-4,
"Position 1 should be weighted average: got {} expected {}",
output[hidden_dim + i],
expected
);
}
}
#[test]
fn test_simplified_attention_causal_mask() {
let config = GpuModelConfig {
vocab_size: 100,
hidden_dim: 8,
num_heads: 2,
num_kv_heads: 2,
num_layers: 2,
intermediate_dim: 32,
eps: 1e-5,
rope_theta: 10000.0,
explicit_head_dim: None,
layer_types: None,
linear_key_head_dim: None,
linear_value_head_dim: None,
linear_num_key_heads: None,
linear_num_value_heads: None,
linear_conv_kernel_dim: None,
constraints: None,
num_experts: None,
num_experts_per_tok: None,
expert_intermediate_size: None,
};
let seq_len = 3;
let hidden_dim = config.hidden_dim;
let v0 = vec![1.0f32; hidden_dim];
let v1 = vec![2.0f32; hidden_dim];
let v2 = vec![3.0f32; hidden_dim];
let qk = vec![1.0f32; hidden_dim];
let mut qkv = Vec::with_capacity(seq_len * 3 * hidden_dim);
for _ in 0..seq_len {
qkv.extend(&qk);
}
for _ in 0..seq_len {
qkv.extend(&qk);
}
qkv.extend(&v0);
qkv.extend(&v1);
qkv.extend(&v2);
let result = simplified_attention(&config, &qkv, seq_len);
assert!(result.is_ok());
let output = result.expect("test value should be present");
assert_eq!(output.len(), seq_len * hidden_dim);
for i in 0..hidden_dim {
assert!((output[i] - 1.0).abs() < 1e-4);
}
for i in 0..hidden_dim {
assert!((output[hidden_dim + i] - 1.5).abs() < 1e-4);
}
for i in 0..hidden_dim {
assert!((output[2 * hidden_dim + i] - 2.0).abs() < 1e-4);
}
}
#[test]
fn test_argmax_with_subnormal_numbers() {
let logits = vec![f32::MIN_POSITIVE, 0.0, f32::MIN_POSITIVE * 2.0];
let result = argmax(&logits);
assert_eq!(result, 2);
}
#[test]
fn test_argmax_very_close_values() {
let logits = vec![
1.0000001, 1.0000002, 1.0000000,
];
let result = argmax(&logits);
assert_eq!(result, 1);
}
#[test]
fn test_optimized_lm_head_argmax_zero_hidden() {
let hidden = vec![0.0, 0.0, 0.0, 0.0];
let weight_t = vec![1.0, 2.0, 3.0, 4.0, 0.0, 0.0, 0.0, 0.0];
let bias = vec![5.0, 10.0];
let result = optimized_lm_head_argmax_transposed(&hidden, &weight_t, &bias, 4, 2);
assert_eq!(result, 1); }
#[test]
fn test_argmax_chunk_boundary_exact() {
let mut logits = vec![0.0f32; 4096];
logits[4095] = 100.0;
let result = argmax(&logits);
assert_eq!(result, 4095);
}
#[test]
fn test_argmax_chunk_boundary_plus_one() {
let mut logits = vec![0.0f32; 4097];
logits[4096] = 100.0;
let result = argmax(&logits);
assert_eq!(result, 4096);
}
#[test]
fn test_argmax_two_full_chunks() {
let mut logits = vec![0.0f32; 8192];
logits[8191] = 100.0;
let result = argmax(&logits);
assert_eq!(result, 8191);
}