#[test]
fn test_parity013e_optimization_path_updated() {
struct ActualPerformance {
name: &'static str,
measured_tps: f64,
status: &'static str,
}
struct OptimizationPath {
stages: Vec<ActualPerformance>,
target_tps: f64,
}
impl OptimizationPath {
fn current_tps(&self) -> f64 {
self.stages.last().map_or(0.0, |s| s.measured_tps)
}
fn remaining_gap(&self) -> f64 {
self.target_tps / self.current_tps()
}
fn print_status(&self) {
println!("\nPARITY-013e: Optimization Path Status");
for stage in &self.stages {
println!(
" {}: {:.2} tok/s [{}]",
stage.name, stage.measured_tps, stage.status
);
}
println!(" Target: {:.0} tok/s (Ollama)", self.target_tps);
println!(" Current gap: {:.1}x", self.remaining_gap());
}
}
let path = OptimizationPath {
stages: vec![
ActualPerformance {
name: "Baseline (scalar)",
measured_tps: 0.17,
status: "VERIFIED",
},
ActualPerformance {
name: "KV Cache + SIMD",
measured_tps: 5.09,
status: "VERIFIED (imp_700)",
},
ActualPerformance {
name: "Fused Q4_K kernels",
measured_tps: 5.09, status: "INTEGRATED",
},
ActualPerformance {
name: "FlashAttention (projected)",
measured_tps: 20.36, status: "PLANNED (IMP-308)",
},
ActualPerformance {
name: "Batch GEMM (projected)",
measured_tps: 38.47, status: "PLANNED (batch inference)",
},
],
target_tps: 225.0, };
path.print_status();
let current = path
.stages
.iter()
.filter(|s| s.status.contains("VERIFIED") || s.status.contains("INTEGRATED"))
.next_back()
.expect("Should have verified stages");
assert!(
current.measured_tps >= 4.0,
"PARITY-013e: Current verified performance should be ~5 tok/s"
);
let gap = path.remaining_gap();
assert!(
gap < 100.0,
"PARITY-013e: Gap should be <100x after KV cache (was 1090x)"
);
assert!(
gap > 5.0,
"PARITY-013e: Gap should still be >5x (need more optimizations)"
);
println!("\n Next steps for parity:");
println!(" 1. Implement FlashAttention (IMP-308) → ~4x");
println!(" 2. Enable batch inference for GPU GEMM → ~sqrt(57)x");
println!(" 3. Combined: projected ~38 tok/s, 5.9x gap remaining");
println!(" Status: VERIFIED - Clear path to parity identified");
}
#[test]
fn test_parity014a_gpu_batch_matmul() {
use crate::gpu::HybridScheduler;
struct BatchMatmulBenchmark {
batch_size: usize,
m: usize,
k: usize,
n: usize,
gpu_used: bool,
speedup_expected: f64,
}
impl BatchMatmulBenchmark {
fn new(batch_size: usize, k: usize, n: usize) -> Self {
Self {
batch_size,
m: batch_size,
k,
n,
gpu_used: batch_size >= 32, speedup_expected: if batch_size >= 32 { 10.0 } else { 1.0 },
}
}
fn should_use_gpu(&self) -> bool {
self.m >= 32 && self.k >= 512 && self.n >= 512
}
fn workload(&self) -> usize {
self.m * self.k * self.n
}
}
let benchmarks = vec![
BatchMatmulBenchmark::new(1, 2560, 10240), BatchMatmulBenchmark::new(8, 2560, 10240), BatchMatmulBenchmark::new(32, 2560, 10240), BatchMatmulBenchmark::new(64, 2560, 10240), ];
println!("\nPARITY-014a: GPU Batch Matmul Analysis");
for bench in &benchmarks {
let gpu_decision = if bench.should_use_gpu() {
"GPU GEMM"
} else {
"CPU SIMD"
};
println!(
" batch={}: [{}x{}x{}] = {} (workload: {} ops)",
bench.batch_size,
bench.m,
bench.k,
bench.n,
gpu_decision,
bench.workload()
);
}
let single = &benchmarks[0];
let batch = &benchmarks[3];
assert!(
!single.should_use_gpu(),
"PARITY-014a: Single request should use CPU"
);
assert!(
batch.should_use_gpu(),
"PARITY-014a: Large batch should use GPU"
);
if let Ok(scheduler) = HybridScheduler::new() {
assert!(
!scheduler.should_use_gpu(1, 2560, 10240),
"PARITY-014a: HybridScheduler should use CPU for m=1"
);
let large_batch_gpu = scheduler.should_use_gpu(64, 2560, 10240);
println!(" HybridScheduler has GPU: {}", scheduler.has_gpu());
if scheduler.has_gpu() {
assert!(
large_batch_gpu,
"PARITY-014a: HybridScheduler should use GPU for large batch"
);
}
}
println!(" Status: VERIFIED - GPU dispatch decisions correct");
}
#[test]
fn test_parity014b_batched_ffn_gpu() {
struct FFNConfig {
hidden_dim: usize,
intermediate_dim: usize, }
impl FFNConfig {
fn phi2() -> Self {
Self {
hidden_dim: 2560,
intermediate_dim: 10240,
}
}
fn up_weight_elements(&self) -> usize {
self.hidden_dim * self.intermediate_dim
}
fn down_weight_elements(&self) -> usize {
self.intermediate_dim * self.hidden_dim
}
fn up_weight_bytes_f32(&self) -> usize {
self.up_weight_elements() * 4
}
}
struct BatchedFFN {
config: FFNConfig,
batch_size: usize,
}
impl BatchedFFN {
fn new(batch_size: usize) -> Self {
Self {
config: FFNConfig::phi2(),
batch_size,
}
}
fn up_matmul_dims(&self) -> (usize, usize, usize) {
(
self.batch_size,
self.config.hidden_dim,
self.config.intermediate_dim,
)
}
fn down_matmul_dims(&self) -> (usize, usize, usize) {
(
self.batch_size,
self.config.intermediate_dim,
self.config.hidden_dim,
)
}
fn is_gpu_beneficial(&self) -> bool {
self.batch_size >= 32
}
fn memory_for_dequant(&self) -> usize {
self.config.up_weight_bytes_f32() + self.config.up_weight_bytes_f32()
}
}
let configs = vec![
BatchedFFN::new(1),
BatchedFFN::new(8),
BatchedFFN::new(32),
BatchedFFN::new(64),
];
println!("\nPARITY-014b: Batched FFN GPU Analysis");
for ffn in &configs {
let (m, k, n) = ffn.up_matmul_dims();
let gpu_status = if ffn.is_gpu_beneficial() {
"GPU GEMM"
} else {
"CPU SIMD"
};
let mem_mb = ffn.memory_for_dequant() as f64 / 1_000_000.0;
println!(
" batch={}: up=[{}x{}x{}] -> {} (dequant mem: {:.1} MB)",
ffn.batch_size, m, k, n, gpu_status, mem_mb
);
}
let single = &configs[0];
let batch64 = &configs[3];
assert!(
!single.is_gpu_beneficial(),
"PARITY-014b: Single request should not use GPU for FFN"
);
assert!(
batch64.is_gpu_beneficial(),
"PARITY-014b: Batch of 64 should use GPU for FFN"
);
let dequant_mem = batch64.memory_for_dequant();
let quantized_mem = dequant_mem / 4; println!("\n Memory overhead for dequantized FFN weights:");
println!(
" Quantized (Q4_K): {:.1} MB",
quantized_mem as f64 / 1_000_000.0
);
println!(
" Dequantized (f32): {:.1} MB",
dequant_mem as f64 / 1_000_000.0
);
println!(
" Overhead: {:.1}x",
dequant_mem as f64 / quantized_mem as f64
);
println!(" Status: VERIFIED - Batched FFN GPU path designed");
}
#[test]
fn test_parity014c_batch_inference_integration() {
struct BatchInferenceModel {
single_request_tps: f64,
batch_size: usize,
gpu_gemm_speedup: f64,
attention_fraction: f64, ffn_fraction: f64, }
impl BatchInferenceModel {
fn new(batch_size: usize) -> Self {
Self {
single_request_tps: 5.09, batch_size,
gpu_gemm_speedup: 10.0, attention_fraction: 0.4, ffn_fraction: 0.6, }
}
fn effective_speedup(&self) -> f64 {
if self.batch_size < 32 {
1.0 + 0.1 * self.batch_size as f64
} else {
let attention_time = self.attention_fraction;
let ffn_time = self.ffn_fraction / self.gpu_gemm_speedup;
1.0 / (attention_time + ffn_time)
}
}
fn projected_tps(&self) -> f64 {
self.single_request_tps * self.effective_speedup()
}
fn total_batch_tps(&self) -> f64 {
self.projected_tps() * self.batch_size as f64
}
}
let models = vec![
BatchInferenceModel::new(1),
BatchInferenceModel::new(8),
BatchInferenceModel::new(32),
BatchInferenceModel::new(64),
];
println!("\nPARITY-014c: Batch Inference Performance Projection");
println!(
" Baseline: {:.2} tok/s (single request)",
models[0].single_request_tps
);
for model in &models {
println!(
" batch={}: speedup={:.1}x, per-request={:.1} tok/s, total={:.0} tok/s",
model.batch_size,
model.effective_speedup(),
model.projected_tps(),
model.total_batch_tps()
);
}
let _single = &models[0];
let batch64 = &models[3];
assert!(
batch64.effective_speedup() > 2.0,
"PARITY-014c: Batch of 64 should provide >2x speedup"
);
assert!(
batch64.total_batch_tps() > 100.0,
"PARITY-014c: Batch of 64 should exceed 100 tok/s total"
);
println!(" Status: VERIFIED - Batch inference integration modeled");
}