#[test]
fn test_streaming_kv_cache_32768_positions() {
let num_layers = 4; let max_positions = 32768;
let num_heads = 8;
let head_dim = 64;
let mut cache = StreamingKVCache::new(num_layers, max_positions, num_heads, head_dim);
assert_eq!(cache.max_positions(), 32768);
assert_eq!(cache.len(), 0);
let kv_dim = num_heads * head_dim;
let key = vec![0.1f32; kv_dim];
let value = vec![0.2f32; kv_dim];
for _pos in 0..32768 {
for layer in 0..num_layers {
cache.append(layer, &key, &value);
}
}
assert_eq!(cache.len(), max_positions);
}
#[test]
fn test_mega_long_context_memory_bound() {
let num_layers = 32;
let max_positions = 32768;
let num_heads = 32;
let head_dim = 128;
let cache = StreamingKVCache::new(num_layers, max_positions, num_heads, head_dim);
let expected_bytes = num_layers * max_positions * num_heads * head_dim * 2 * 4;
assert_eq!(cache.memory_bytes(), expected_bytes);
let memory_gb = cache.memory_mb() / 1024.0;
assert!(
memory_gb < 36.0,
"32768 context KV cache should be < 36 GB, got {:.2} GB",
memory_gb
);
}
#[test]
fn test_mega_long_context_fill_performance() {
use std::time::Instant;
let num_layers = 4;
let max_positions = 32768;
let num_heads = 8;
let head_dim = 64;
let mut cache = StreamingKVCache::new(num_layers, max_positions, num_heads, head_dim);
let kv_dim = num_heads * head_dim;
let key = vec![0.1f32; kv_dim];
let value = vec![0.2f32; kv_dim];
let start = Instant::now();
for _pos in 0..32768 {
for layer in 0..num_layers {
cache.append(layer, &key, &value);
}
}
let elapsed = start.elapsed();
let fill_rate = 32768.0 / elapsed.as_secs_f64();
assert!(
fill_rate > 25.0,
"Fill rate should be > 25 pos/s, got {:.0}",
fill_rate
);
}
#[test]
fn test_f32_f16_conversion_roundtrip() {
let test_values = vec![
0.0f32, 1.0, -1.0, 0.5, -0.5, 0.125, 100.0, -100.0, 0.001, 65504.0,
];
for &original in &test_values {
let fp16_bits = StreamingKVCacheFp16::f32_to_f16(original);
let recovered = StreamingKVCacheFp16::f16_to_f32(fp16_bits);
let error = if original.abs() > 1e-6 {
((recovered - original) / original).abs()
} else {
(recovered - original).abs()
};
assert!(
error < 0.01,
"FP16 roundtrip error too large for {}: got {}, error {}",
original,
recovered,
error
);
}
}
#[test]
fn test_streaming_kv_cache_fp16_basic() {
let num_layers = 2;
let max_positions = 16;
let num_heads = 4;
let head_dim = 8;
let mut cache = StreamingKVCacheFp16::new(num_layers, max_positions, num_heads, head_dim);
assert!(cache.is_empty());
assert_eq!(cache.len(), 0);
assert_eq!(cache.max_positions(), 16);
let kv_dim = num_heads * head_dim;
let key = vec![0.5f32; kv_dim];
let value = vec![0.25f32; kv_dim];
for layer in 0..num_layers {
cache.append(layer, &key, &value);
}
assert_eq!(cache.len(), 1);
let (keys, values) = cache.get_valid_f32(0);
assert_eq!(keys.len(), kv_dim);
assert_eq!(values.len(), kv_dim);
for &k in &keys {
assert!((k - 0.5).abs() < 0.01, "Key mismatch: {}", k);
}
for &v in &values {
assert!((v - 0.25).abs() < 0.01, "Value mismatch: {}", v);
}
}
#[test]
#[ignore = "allocates 100GB+ memory - run with --ignored"]
fn test_streaming_kv_cache_fp16_memory_half() {
let num_layers = 32;
let max_positions = 65536;
let num_heads = 32;
let head_dim = 128;
let cache_fp16 = StreamingKVCacheFp16::new(num_layers, max_positions, num_heads, head_dim);
let cache_fp32 = StreamingKVCache::new(num_layers, max_positions, num_heads, head_dim);
let fp16_bytes = cache_fp16.memory_bytes();
let fp32_bytes = cache_fp32.memory_bytes();
assert_eq!(fp16_bytes * 2, fp32_bytes);
let fp16_gb = cache_fp16.memory_mb() / 1024.0;
assert!(
fp16_gb < 36.0,
"FP16 65536 context should be < 36 GB, got {:.2} GB",
fp16_gb
);
assert!(
fp16_gb > 30.0,
"FP16 65536 context should be > 30 GB, got {:.2} GB",
fp16_gb
);
}
#[test]
#[ignore = "allocates large memory for 65536 positions - run with --ignored"]
fn test_streaming_kv_cache_fp16_65536_positions() {
let num_layers = 4;
let max_positions = 65536;
let num_heads = 8;
let head_dim = 64;
let mut cache = StreamingKVCacheFp16::new(num_layers, max_positions, num_heads, head_dim);
let kv_dim = num_heads * head_dim;
let key = vec![0.1f32; kv_dim];
let value = vec![0.2f32; kv_dim];
for _pos in 0..65536 {
for layer in 0..num_layers {
cache.append(layer, &key, &value);
}
}
assert_eq!(cache.len(), max_positions);
for layer in 0..num_layers {
cache.append(layer, &key, &value);
}
assert_eq!(cache.len(), max_positions); }
#[test]
#[ignore = "allocates 34GB+ memory - run with --ignored"]
fn test_fp16_kv_cache_memory_bound_65536() {
let num_layers = 32;
let max_positions = 65536;
let num_heads = 32;
let head_dim = 128;
let cache = StreamingKVCacheFp16::new(num_layers, max_positions, num_heads, head_dim);
let expected_bytes = num_layers * max_positions * num_heads * head_dim * 2 * 2;
assert_eq!(cache.memory_bytes(), expected_bytes);
let memory_gb = cache.memory_mb() / 1024.0;
assert!(
memory_gb < 36.0,
"65536 context FP16 KV cache should be < 36 GB, got {:.2} GB",
memory_gb
);
}
#[test]
#[ignore = "allocates large memory for 65536 positions - run with --ignored"]
fn test_fp16_kv_cache_fill_performance_65536() {
use std::time::Instant;
let num_layers = 4;
let max_positions = 65536;
let num_heads = 8;
let head_dim = 64;
let mut cache = StreamingKVCacheFp16::new(num_layers, max_positions, num_heads, head_dim);
let kv_dim = num_heads * head_dim;
let key = vec![0.1f32; kv_dim];
let value = vec![0.2f32; kv_dim];
let start = Instant::now();
for _pos in 0..65536 {
for layer in 0..num_layers {
cache.append(layer, &key, &value);
}
}
let elapsed = start.elapsed();
let fill_rate = 65536.0 / elapsed.as_secs_f64();
assert!(
fill_rate > 10.0,
"FP16 fill rate should be > 10 pos/s, got {:.0}",
fill_rate
);
}
#[test]
#[cfg(feature = "cuda")]
fn test_imp_1001a_cuda_executor_matmul_correctness() {
use crate::cuda::CudaExecutor;
if !CudaExecutor::is_available() {
println!("IMP-1001a: CUDA not available, skipping");
return;
}
let mut executor = crate::cuda_executor_or_skip!(0);
let a = vec![1.0f32; 16]; let b = vec![1.0f32; 16]; let mut result = vec![0.0f32; 16];
executor
.gemm(&a, &b, &mut result, 4, 4, 4)
.expect("GEMM failed");
for (i, &val) in result.iter().enumerate() {
assert!(
(val - 4.0).abs() < 1e-3,
"IMP-1001a: Element {} mismatch: got {}, expected 4.0",
i,
val
);
}
let a = vec![2.0f32; 64]; let b = vec![1.0f32; 64]; let mut result = vec![0.0f32; 64];
executor
.gemm(&a, &b, &mut result, 8, 8, 8)
.expect("GEMM 8x8 failed");
for (i, &val) in result.iter().enumerate() {
assert!(
(val - 16.0).abs() < 1e-3,
"IMP-1001a: 8x8 element {} mismatch: got {}, expected 16.0",
i,
val
);
}
}
#[test]
#[cfg(feature = "cuda")]
fn test_imp_1001b_cuda_softmax_correctness() {
use crate::cuda::CudaExecutor;
if !CudaExecutor::is_available() {
println!("IMP-1001b: CUDA not available, skipping");
return;
}
let mut executor = crate::cuda_executor_or_skip!(0);
let mut data = vec![1.0, 2.0, 3.0, 4.0];
executor.softmax(&mut data).expect("Softmax failed");
let sum: f32 = data.iter().sum();
assert!(
(sum - 1.0).abs() < 1e-5,
"IMP-1001b: Softmax should sum to 1, got {}",
sum
);
assert!(
data[0] < data[1] && data[1] < data[2] && data[2] < data[3],
"IMP-1001b: Softmax should preserve ordering"
);
}
#[test]
#[cfg(feature = "cuda")]
#[allow(clippy::many_single_char_names)]
fn test_imp_1001c_cuda_inference_speedup() {
use crate::cuda::CudaExecutor;
use std::time::Instant;
if !CudaExecutor::is_available() {
println!("IMP-1001c: CUDA not available, skipping");
return;
}
let mut executor = crate::cuda_executor_or_skip!(0);
let m: u32 = 512;
let k: u32 = 2048;
let n: u32 = 2048;
let a: Vec<f32> = (0..(m * k) as usize)
.map(|i| (i % 100) as f32 * 0.01)
.collect();
let b: Vec<f32> = (0..(k * n) as usize)
.map(|i| (i % 100) as f32 * 0.01)
.collect();
let mut result = vec![0.0f32; (m * n) as usize];
let _ = executor.gemm(&a, &b, &mut result, m, n, k);
let start = Instant::now();
executor
.gemm(&a, &b, &mut result, m, n, k)
.expect("GEMM failed");
let cuda_time = start.elapsed();
let start = Instant::now();
let _cpu_result = cpu_matmul(&a, &b, m as usize, k as usize, n as usize);
let cpu_time = start.elapsed();
let speedup = cpu_time.as_secs_f64() / cuda_time.as_secs_f64();
println!(
"IMP-1001c: CUDA={:.2}ms, CPU={:.2}ms, speedup={:.1}x",
cuda_time.as_secs_f64() * 1000.0,
cpu_time.as_secs_f64() * 1000.0,
speedup
);
assert!(
speedup > 5.0,
"IMP-1001c: CUDA should be >5x faster for 512x2048x2048 GEMM, got {:.1}x",
speedup
);
}