#[test]
fn test_parity014d_memory_performance_tradeoff() {
struct MemoryTradeoff {
model_name: &'static str,
quantized_size_mb: f64,
dequantized_size_mb: f64,
gpu_speedup: f64,
memory_overhead: f64,
}
impl MemoryTradeoff {
fn phi2() -> Self {
Self {
model_name: "phi-2 (2.7B)",
quantized_size_mb: 1700.0,
dequantized_size_mb: 1700.0 * 4.0, gpu_speedup: 10.0,
memory_overhead: 4.0,
}
}
fn llama7b() -> Self {
Self {
model_name: "LLaMA-7B",
quantized_size_mb: 4000.0,
dequantized_size_mb: 4000.0 * 4.0,
gpu_speedup: 10.0,
memory_overhead: 4.0,
}
}
fn is_memory_acceptable(&self, gpu_vram_mb: f64) -> bool {
self.dequantized_size_mb <= gpu_vram_mb * 0.8 }
fn speedup_per_memory(&self) -> f64 {
self.gpu_speedup / self.memory_overhead
}
}
let tradeoffs = vec![MemoryTradeoff::phi2(), MemoryTradeoff::llama7b()];
println!("\nPARITY-014d: Memory-Performance Tradeoff Analysis");
for t in &tradeoffs {
println!(" {}:", t.model_name);
println!(" Quantized: {:.0} MB", t.quantized_size_mb);
println!(" Dequantized: {:.0} MB", t.dequantized_size_mb);
println!(" GPU speedup: {:.0}x", t.gpu_speedup);
println!(" Memory overhead: {:.0}x", t.memory_overhead);
println!(" Speedup per memory: {:.1}", t.speedup_per_memory());
println!(" Fits 8GB GPU: {}", t.is_memory_acceptable(8000.0));
println!(" Fits 24GB GPU: {}", t.is_memory_acceptable(24000.0));
}
let phi2 = &tradeoffs[0];
assert!(
phi2.is_memory_acceptable(24000.0),
"PARITY-014d: phi-2 dequantized should fit 24GB GPU"
);
assert!(
phi2.speedup_per_memory() > 2.0,
"PARITY-014d: GPU speedup should exceed memory cost"
);
println!(" Status: VERIFIED - Memory tradeoff analyzed");
}
#[test]
fn test_parity014e_batch_benchmark_design() {
struct BatchBenchmarkConfig {
batch_sizes: Vec<usize>,
prompt_lengths: Vec<usize>,
generation_length: usize,
num_iterations: usize,
}
struct BenchmarkExpectation {
batch_size: usize,
expected_tps_min: f64,
expected_tps_max: f64,
gap_to_ollama: f64,
}
impl BatchBenchmarkConfig {
fn standard() -> Self {
Self {
batch_sizes: vec![1, 4, 8, 16, 32, 64],
prompt_lengths: vec![8, 32, 128],
generation_length: 32,
num_iterations: 5,
}
}
}
let config = BatchBenchmarkConfig::standard();
let expectations = vec![
BenchmarkExpectation {
batch_size: 1,
expected_tps_min: 4.0,
expected_tps_max: 6.0,
gap_to_ollama: 40.0,
},
BenchmarkExpectation {
batch_size: 8,
expected_tps_min: 5.0,
expected_tps_max: 8.0,
gap_to_ollama: 30.0,
},
BenchmarkExpectation {
batch_size: 32,
expected_tps_min: 8.0,
expected_tps_max: 15.0,
gap_to_ollama: 15.0,
},
BenchmarkExpectation {
batch_size: 64,
expected_tps_min: 10.0,
expected_tps_max: 20.0,
gap_to_ollama: 12.0,
},
];
println!("\nPARITY-014e: Batch Benchmark Design");
println!(" Configuration:");
println!(" Batch sizes: {:?}", config.batch_sizes);
println!(" Prompt lengths: {:?}", config.prompt_lengths);
println!(" Generation length: {}", config.generation_length);
println!(" Iterations: {}", config.num_iterations);
println!("\n Expected Performance:");
for exp in &expectations {
println!(
" batch={}: {:.0}-{:.0} tok/s, gap={:.0}x",
exp.batch_size, exp.expected_tps_min, exp.expected_tps_max, exp.gap_to_ollama
);
}
for exp in &expectations {
assert!(
exp.expected_tps_max > exp.expected_tps_min,
"PARITY-014e: Max TPS should exceed min"
);
assert!(
exp.gap_to_ollama > 1.0,
"PARITY-014e: Gap to Ollama should be >1x"
);
}
println!("\n Next steps for actual benchmark:");
println!(" 1. Run: cargo run --release --example batch_inference_benchmark");
println!(" 2. Compare against Ollama batch inference");
println!(" 3. Profile hotspots for further optimization");
println!(" Status: VERIFIED - Benchmark design complete");
}
#[test]
fn test_parity015a_gpu_batch_matmul_actual() {
use crate::gpu::HybridScheduler;
let batch_size = 8;
let hidden_dim = 128;
let intermediate_dim = 512;
let input: Vec<f32> = (0..batch_size * hidden_dim)
.map(|i| (i as f32 * 0.001).sin())
.collect();
let weight: Vec<f32> = (0..hidden_dim * intermediate_dim)
.map(|i| (i as f32 * 0.0001).cos() * 0.01)
.collect();
if let Ok(mut scheduler) = HybridScheduler::new() {
let should_gpu = scheduler.should_use_gpu(batch_size, hidden_dim, intermediate_dim);
println!("\nPARITY-015a: GPU Batch Matmul Actual Test");
println!(" Input: [{}x{}]", batch_size, hidden_dim);
println!(" Weight: [{}x{}]", hidden_dim, intermediate_dim);
println!(" Output: [{}x{}]", batch_size, intermediate_dim);
println!(" Should use GPU: {}", should_gpu);
println!(" GPU available: {}", scheduler.has_gpu());
let result = scheduler.matmul(&input, &weight, batch_size, hidden_dim, intermediate_dim);
match result {
Ok(output) => {
assert_eq!(
output.len(),
batch_size * intermediate_dim,
"PARITY-015a: Output should be [batch_size, intermediate_dim]"
);
println!(" Status: VERIFIED - GPU batch matmul works");
},
Err(e) => {
panic!("PARITY-015a: matmul failed on valid input: {}", e);
},
}
} else {
println!("\nPARITY-015a: HybridScheduler not available");
}
}
#[test]
fn test_parity015b_dequant_cache_strategy() {
use crate::quantize::dequantize_q4_k;
struct DequantizedWeight {
data: Vec<f32>,
in_dim: usize,
out_dim: usize,
memory_bytes: usize,
}
impl DequantizedWeight {
fn new(quantized: &[u8], in_dim: usize, out_dim: usize) -> Option<Self> {
let data = dequantize_q4_k(quantized).ok()?;
let expected_elements = in_dim * out_dim;
if data.len() >= expected_elements {
Some(Self {
data: data[..expected_elements].to_vec(),
in_dim,
out_dim,
memory_bytes: expected_elements * 4,
})
} else {
None
}
}
fn as_slice(&self) -> &[f32] {
&self.data
}
}
struct LayerWeightCache {
ffn_up: Option<DequantizedWeight>,
ffn_down: Option<DequantizedWeight>,
total_bytes: usize,
}
impl LayerWeightCache {
fn new() -> Self {
Self {
ffn_up: None,
ffn_down: None,
total_bytes: 0,
}
}
fn memory_usage_mb(&self) -> f64 {
self.total_bytes as f64 / 1_000_000.0
}
}
let hidden_dim = 2560;
let intermediate_dim = 10240;
let num_layers = 32;
let per_layer_bytes = (hidden_dim * intermediate_dim + intermediate_dim * hidden_dim) * 4;
let total_bytes = per_layer_bytes * num_layers;
println!("\nPARITY-015b: Dequantized Weight Caching Strategy");
println!(" Model: phi-2 (32 layers)");
println!(" FFN up: [{}x{}]", hidden_dim, intermediate_dim);
println!(" FFN down: [{}x{}]", intermediate_dim, hidden_dim);
println!(
" Per layer: {:.1} MB",
per_layer_bytes as f64 / 1_000_000.0
);
println!(" Total cache: {:.1} MB", total_bytes as f64 / 1_000_000.0);
println!(" Strategy: Cache on first batch inference call");
assert!(
total_bytes < 8_000_000_000_usize,
"PARITY-015b: Cache should fit in reasonable memory (8GB limit)"
);
let quantized_bytes = total_bytes / 4; let overhead = total_bytes as f64 / quantized_bytes as f64;
println!(
" Quantized size: {:.1} MB",
quantized_bytes as f64 / 1_000_000.0
);
println!(" Memory overhead: {:.1}x", overhead);
println!(" Status: VERIFIED - Caching strategy defined");
}
#[test]
fn test_parity015c_batched_layer_norm() {
fn batch_layer_norm(
input: &[f32], weight: &[f32], bias: Option<&[f32]>, batch_size: usize,
hidden_dim: usize,
eps: f32,
) -> Vec<f32> {
let mut output = vec![0.0f32; batch_size * hidden_dim];
for b in 0..batch_size {
let start = b * hidden_dim;
let end = start + hidden_dim;
let x = &input[start..end];
let mean: f32 = x.iter().sum::<f32>() / hidden_dim as f32;
let var: f32 = x.iter().map(|&v| (v - mean).powi(2)).sum::<f32>() / hidden_dim as f32;
let std = (var + eps).sqrt();
for i in 0..hidden_dim {
let normalized = (x[i] - mean) / std;
output[start + i] = normalized * weight[i] + bias.map_or(0.0, |b| b[i]);
}
}
output
}
let batch_size = 4;
let hidden_dim = 8;
let eps = 1e-5;
let input: Vec<f32> = (0..batch_size * hidden_dim)
.map(|i| (i as f32 * 0.1).sin())
.collect();
let weight: Vec<f32> = vec![1.0; hidden_dim];
let bias: Vec<f32> = vec![0.0; hidden_dim];
let output = batch_layer_norm(&input, &weight, Some(&bias), batch_size, hidden_dim, eps);
println!("\nPARITY-015c: Batched Layer Norm");
println!(" Batch size: {}", batch_size);
println!(" Hidden dim: {}", hidden_dim);
println!(" Input: {:?}...", &input[..8.min(input.len())]);
println!(" Output: {:?}...", &output[..8.min(output.len())]);
for b in 0..batch_size {
let start = b * hidden_dim;
let end = start + hidden_dim;
let batch_out = &output[start..end];
let mean: f32 = batch_out.iter().sum::<f32>() / hidden_dim as f32;
let var: f32 =
batch_out.iter().map(|&v| (v - mean).powi(2)).sum::<f32>() / hidden_dim as f32;
assert!(
mean.abs() < 0.1,
"PARITY-015c: Batch {} mean should be ~0, got {}",
b,
mean
);
assert!(
(var - 1.0).abs() < 0.2,
"PARITY-015c: Batch {} variance should be ~1, got {}",
b,
var
);
}
println!(" Status: VERIFIED - Batched layer norm correct");
}