use super::*;
#[test]
fn test_backend_selection_small_matmul() {
let selector = BackendSelector::new();
let backend = selector.select_for_matmul(64, 64, 64);
assert_eq!(backend, Backend::SIMD);
}
#[test]
fn test_backend_selection_large_matmul() {
let selector = BackendSelector::new();
let backend = selector.select_for_matmul(512, 512, 512);
assert_eq!(backend, Backend::SIMD);
}
#[test]
fn test_backend_selection_very_large_matmul() {
let selector = BackendSelector::new();
let backend = selector.select_for_matmul(2048, 2048, 2048);
assert_eq!(backend, Backend::SIMD);
}
#[test]
fn test_backend_selection_dot_product() {
let selector = BackendSelector::new();
let backend = selector.select_for_vector_op(10_000, 2);
assert_eq!(backend, Backend::SIMD); }
#[test]
fn test_backend_selection_elementwise() {
let selector = BackendSelector::new();
let backend = selector.select_for_elementwise(1000);
assert_eq!(backend, Backend::Scalar);
let backend = selector.select_for_elementwise(2_000_000);
assert_eq!(backend, Backend::SIMD);
}
#[test]
fn test_custom_dispatch_ratio() {
let selector = BackendSelector::new().with_min_dispatch_ratio(10.0);
let backend = selector.select_backend(1_000_000, 30_000_000);
assert_eq!(backend, Backend::SIMD);
}
#[test]
fn test_moe_low_complexity() {
let selector = BackendSelector::new();
assert_eq!(selector.select_with_moe(OpComplexity::Low, 100), Backend::Scalar);
assert_eq!(selector.select_with_moe(OpComplexity::Low, 2_000_000), Backend::SIMD);
assert_ne!(selector.select_with_moe(OpComplexity::Low, 10_000_000), Backend::GPU);
}
#[test]
fn test_moe_medium_complexity() {
let selector = BackendSelector::new();
assert_eq!(selector.select_with_moe(OpComplexity::Medium, 1_000), Backend::Scalar);
assert_eq!(selector.select_with_moe(OpComplexity::Medium, 50_000), Backend::SIMD);
assert_eq!(selector.select_with_moe(OpComplexity::Medium, 200_000), Backend::GPU);
}
#[test]
fn test_moe_high_complexity() {
let selector = BackendSelector::new();
assert_eq!(selector.select_with_moe(OpComplexity::High, 500), Backend::Scalar);
assert_eq!(selector.select_with_moe(OpComplexity::High, 5_000), Backend::SIMD);
assert_eq!(selector.select_with_moe(OpComplexity::High, 50_000), Backend::GPU);
}
#[test]
#[cfg(feature = "trueno-integration")]
fn test_trueno_vector_add() {
let selector = BackendSelector::new();
let a = vec![1.0, 2.0, 3.0, 4.0];
let b = vec![5.0, 6.0, 7.0, 8.0];
let result = selector.vector_add(&a, &b).unwrap();
assert_eq!(result, vec![6.0, 8.0, 10.0, 12.0]);
}
#[test]
#[cfg(feature = "trueno-integration")]
fn test_trueno_matrix_multiply() {
let selector = BackendSelector::new();
let a = vec![1.0, 2.0, 3.0, 4.0]; let b = vec![5.0, 6.0, 7.0, 8.0];
let result = selector.matrix_multiply(&a, &b, 2, 2, 2).unwrap();
assert_eq!(result, vec![19.0, 22.0, 43.0, 50.0]);
}
#[test]
fn test_select_backend_arithmetic_correctness() {
let selector = BackendSelector::new();
let pcie_bw = 32e9; let gpu_gflops = 20e12;
let data_bytes = 1_000_000; let transfer_s = data_bytes as f64 / pcie_bw;
let compute_s_threshold = 5.0 * transfer_s;
let flops = (compute_s_threshold * gpu_gflops) as u64;
let backend = selector.select_backend(data_bytes, flops);
assert_eq!(backend, Backend::SIMD, "At exactly 5x threshold, should choose SIMD");
let flops_above = (flops as f64 * 1.01) as u64; let backend = selector.select_backend(data_bytes, flops_above);
assert_eq!(backend, Backend::GPU, "Above 5x threshold, should choose GPU");
let flops_below = flops / 2;
let backend = selector.select_backend(data_bytes, flops_below);
assert_eq!(backend, Backend::SIMD, "Below 5x threshold, should choose SIMD");
}
#[test]
fn test_select_backend_arithmetic_mutation_detection() {
let selector = BackendSelector::new();
let data_bytes = 1_000_000_000;
let flops = 1_000_000_000_000_000;
let backend = selector.select_backend(data_bytes, flops);
assert_eq!(backend, Backend::GPU, "High compute/transfer ratio should select GPU");
let flops_low = 1_000_000_000;
let backend = selector.select_backend(data_bytes, flops_low);
assert_eq!(backend, Backend::SIMD, "Low compute/transfer ratio should select SIMD");
}
#[test]
fn test_matmul_data_bytes_calculation() {
let selector = BackendSelector::new();
let m = 100;
let n = 100;
let k = 100;
let backend = selector.select_for_matmul(m, n, k);
assert_eq!(backend, Backend::SIMD);
let slow_selector = BackendSelector::new()
.with_pcie_bandwidth(1e9) .with_gpu_gflops(100e12);
let m_large = 1000;
let n_large = 1000;
let k_large = 1000;
let backend = slow_selector.select_for_matmul(m_large, n_large, k_large);
assert_eq!(backend, Backend::SIMD);
}
#[test]
fn test_matmul_flops_calculation() {
let selector = BackendSelector::new().with_gpu_gflops(1e12);
let m = 10;
let n = 10;
let k = 10;
let backend = selector.select_for_matmul(m, n, k);
assert_eq!(backend, Backend::SIMD);
}
#[test]
fn test_vector_op_data_bytes_calculation() {
let selector = BackendSelector::new();
let n = 1000;
let ops_per_element = 2;
let backend = selector.select_for_vector_op(n, ops_per_element);
assert_eq!(backend, Backend::SIMD);
}
#[test]
fn test_vector_op_flops_calculation() {
let selector = BackendSelector::new().with_gpu_gflops(1e12);
let n = 10000;
let ops_per_element = 10;
let backend = selector.select_for_vector_op(n, ops_per_element);
assert_eq!(backend, Backend::SIMD);
}
#[test]
fn test_dispatch_ratio_multiplication() {
let selector_5x = BackendSelector::new().with_min_dispatch_ratio(5.0);
let selector_10x = BackendSelector::new().with_min_dispatch_ratio(10.0);
let data_bytes = 1_000_000;
let pcie_bw = 32e9;
let gpu_gflops = 20e12;
let transfer_s = data_bytes as f64 / pcie_bw;
let compute_s_7x = 7.0 * transfer_s;
let flops = (compute_s_7x * gpu_gflops) as u64;
let backend = selector_5x.select_backend(data_bytes, flops);
assert_eq!(backend, Backend::GPU, "7x should exceed 5x threshold");
let backend = selector_10x.select_backend(data_bytes, flops);
assert_eq!(backend, Backend::SIMD, "7x should not exceed 10x threshold");
}
#[test]
fn test_moe_low_complexity_boundary() {
let selector = BackendSelector::new();
assert_eq!(
selector.select_with_moe(OpComplexity::Low, 1_000_000),
Backend::Scalar,
"Exactly 1M elements should be Scalar (> not >=)"
);
assert_eq!(
selector.select_with_moe(OpComplexity::Low, 1_000_001),
Backend::SIMD,
"1M+1 elements should be SIMD"
);
assert_eq!(
selector.select_with_moe(OpComplexity::Low, 999_999),
Backend::Scalar,
"1M-1 elements should be Scalar"
);
}
#[test]
fn test_moe_medium_complexity_boundaries() {
let selector = BackendSelector::new();
assert_eq!(
selector.select_with_moe(OpComplexity::Medium, 10_000),
Backend::Scalar,
"Exactly 10K should be Scalar"
);
assert_eq!(
selector.select_with_moe(OpComplexity::Medium, 10_001),
Backend::SIMD,
"10K+1 should be SIMD"
);
assert_eq!(
selector.select_with_moe(OpComplexity::Medium, 9_999),
Backend::Scalar,
"10K-1 should be Scalar"
);
assert_eq!(
selector.select_with_moe(OpComplexity::Medium, 100_000),
Backend::SIMD,
"Exactly 100K should be SIMD"
);
assert_eq!(
selector.select_with_moe(OpComplexity::Medium, 100_001),
Backend::GPU,
"100K+1 should be GPU"
);
assert_eq!(
selector.select_with_moe(OpComplexity::Medium, 99_999),
Backend::SIMD,
"100K-1 should be SIMD"
);
}
#[test]
fn test_moe_high_complexity_boundaries() {
let selector = BackendSelector::new();
assert_eq!(
selector.select_with_moe(OpComplexity::High, 1_000),
Backend::Scalar,
"Exactly 1K should be Scalar"
);
assert_eq!(
selector.select_with_moe(OpComplexity::High, 1_001),
Backend::SIMD,
"1K+1 should be SIMD"
);
assert_eq!(
selector.select_with_moe(OpComplexity::High, 999),
Backend::Scalar,
"1K-1 should be Scalar"
);
assert_eq!(
selector.select_with_moe(OpComplexity::High, 10_000),
Backend::SIMD,
"Exactly 10K should be SIMD"
);
assert_eq!(
selector.select_with_moe(OpComplexity::High, 10_001),
Backend::GPU,
"10K+1 should be GPU"
);
assert_eq!(
selector.select_with_moe(OpComplexity::High, 9_999),
Backend::SIMD,
"10K-1 should be SIMD"
);
}
#[test]
fn test_elementwise_boundary() {
let selector = BackendSelector::new();
assert_eq!(
selector.select_for_elementwise(1_000_000),
Backend::Scalar,
"Exactly 1M should be Scalar"
);
assert_eq!(selector.select_for_elementwise(1_000_001), Backend::SIMD, "1M+1 should be SIMD");
assert_eq!(selector.select_for_elementwise(999_999), Backend::Scalar, "1M-1 should be Scalar");
}
#[test]
fn test_zero_size_operations() {
let selector = BackendSelector::new();
let backend = selector.select_for_matmul(0, 0, 0);
assert_eq!(backend, Backend::SIMD);
let backend = selector.select_for_vector_op(0, 1);
assert_eq!(backend, Backend::SIMD);
let backend = selector.select_for_elementwise(0);
assert_eq!(backend, Backend::Scalar);
assert_eq!(selector.select_with_moe(OpComplexity::Low, 0), Backend::Scalar);
assert_eq!(selector.select_with_moe(OpComplexity::Medium, 0), Backend::Scalar);
assert_eq!(selector.select_with_moe(OpComplexity::High, 0), Backend::Scalar);
}
#[test]
fn test_single_element_operations() {
let selector = BackendSelector::new();
assert_eq!(selector.select_with_moe(OpComplexity::Low, 1), Backend::Scalar);
assert_eq!(selector.select_with_moe(OpComplexity::Medium, 1), Backend::Scalar);
assert_eq!(selector.select_with_moe(OpComplexity::High, 1), Backend::Scalar);
assert_eq!(selector.select_for_elementwise(1), Backend::Scalar);
}
#[test]
fn test_very_large_operations() {
let selector = BackendSelector::new();
let huge_size = 1_000_000_000;
assert_eq!(selector.select_with_moe(OpComplexity::Low, huge_size), Backend::SIMD);
assert_eq!(selector.select_with_moe(OpComplexity::Medium, huge_size), Backend::GPU);
assert_eq!(selector.select_with_moe(OpComplexity::High, huge_size), Backend::GPU);
}
#[test]
fn test_custom_hardware_params() {
let slow_pcie_selector = BackendSelector::new()
.with_pcie_bandwidth(1e9) .with_gpu_gflops(100e12);
let fast_pcie_selector = BackendSelector::new()
.with_pcie_bandwidth(100e9) .with_gpu_gflops(1e12);
let data_bytes_low = 1_000_000;
let flops_low = 1_000_000_000;
let backend = slow_pcie_selector.select_backend(data_bytes_low, flops_low);
assert_eq!(backend, Backend::SIMD);
let backend = fast_pcie_selector.select_backend(data_bytes_low, flops_low);
assert_eq!(backend, Backend::GPU);
let data_bytes_high = 1_000_000;
let flops_high = 1_000_000_000_000;
let backend = slow_pcie_selector.select_backend(data_bytes_high, flops_high);
assert_eq!(backend, Backend::GPU);
let backend = fast_pcie_selector.select_backend(data_bytes_high, flops_high);
assert_eq!(backend, Backend::GPU);
}
#[test]
fn test_backend_display() {
assert_eq!(format!("{}", Backend::Scalar), "Scalar");
assert_eq!(format!("{}", Backend::SIMD), "SIMD");
assert_eq!(format!("{}", Backend::GPU), "GPU");
}
#[test]
fn test_backend_equality() {
assert_eq!(Backend::Scalar, Backend::Scalar);
assert_eq!(Backend::SIMD, Backend::SIMD);
assert_eq!(Backend::GPU, Backend::GPU);
assert_ne!(Backend::Scalar, Backend::SIMD);
assert_ne!(Backend::SIMD, Backend::GPU);
assert_ne!(Backend::Scalar, Backend::GPU);
}
#[test]
fn test_backend_clone_copy() {
let b1 = Backend::GPU;
let b2 = b1; assert_eq!(b1, b2);
let b3 = b1; assert_eq!(b1, b3);
}
#[test]
fn test_backend_debug() {
let backend = Backend::SIMD;
let debug_str = format!("{:?}", backend);
assert!(debug_str.contains("SIMD"));
}
#[test]
fn test_backend_serialization() {
let backend = Backend::GPU;
let json = serde_json::to_string(&backend).unwrap();
let deserialized: Backend = serde_json::from_str(&json).unwrap();
assert_eq!(backend, deserialized);
for backend in &[Backend::Scalar, Backend::SIMD, Backend::GPU] {
let json = serde_json::to_string(backend).unwrap();
let deserialized: Backend = serde_json::from_str(&json).unwrap();
assert_eq!(*backend, deserialized);
}
}
#[test]
fn test_op_complexity_ordering() {
assert!(OpComplexity::Low < OpComplexity::Medium);
assert!(OpComplexity::Medium < OpComplexity::High);
assert!(OpComplexity::Low < OpComplexity::High);
assert!(OpComplexity::High > OpComplexity::Medium);
assert!(OpComplexity::Medium > OpComplexity::Low);
assert!(OpComplexity::High > OpComplexity::Low);
}
#[test]
fn test_op_complexity_equality() {
assert_eq!(OpComplexity::Low, OpComplexity::Low);
assert_eq!(OpComplexity::Medium, OpComplexity::Medium);
assert_eq!(OpComplexity::High, OpComplexity::High);
assert_ne!(OpComplexity::Low, OpComplexity::Medium);
assert_ne!(OpComplexity::Medium, OpComplexity::High);
}
#[test]
fn test_op_complexity_clone_copy() {
let c1 = OpComplexity::High;
let c2 = c1; assert_eq!(c1, c2);
let c3 = c1; assert_eq!(c1, c3);
}
#[test]
fn test_op_complexity_debug() {
let complexity = OpComplexity::Medium;
let debug_str = format!("{:?}", complexity);
assert!(debug_str.contains("Medium"));
}
#[test]
fn test_backend_selector_new() {
let selector = BackendSelector::new();
let backend = selector.select_backend(1_000_000, 1_000_000_000);
assert_eq!(backend, Backend::SIMD);
}
#[test]
fn test_backend_selector_default() {
let selector1 = BackendSelector::new();
let selector2 = BackendSelector::default();
let backend1 = selector1.select_backend(1_000_000, 1_000_000_000);
let backend2 = selector2.select_backend(1_000_000, 1_000_000_000);
assert_eq!(backend1, backend2);
}
#[test]
fn test_backend_selector_with_pcie_bandwidth() {
let selector = BackendSelector::new().with_pcie_bandwidth(64e9);
let backend = selector.select_backend(1_000_000, 1_000_000_000);
assert_eq!(backend, Backend::SIMD);
}
#[test]
fn test_backend_selector_with_gpu_gflops() {
let selector = BackendSelector::new().with_gpu_gflops(10e12);
let backend = selector.select_backend(1_000_000, 1_000_000_000);
assert_eq!(backend, Backend::SIMD);
}
#[test]
fn test_backend_selector_with_min_dispatch_ratio() {
let selector = BackendSelector::new().with_min_dispatch_ratio(2.0);
let backend = selector.select_backend(1_000_000, 1_000_000_000);
assert_eq!(backend, Backend::SIMD);
}
#[test]
fn test_backend_selector_builder_chaining() {
let selector = BackendSelector::new()
.with_pcie_bandwidth(16e9)
.with_gpu_gflops(50e12)
.with_min_dispatch_ratio(3.0);
let backend = selector.select_backend(1_000_000, 10_000_000_000);
assert!(backend == Backend::GPU || backend == Backend::SIMD);
}
#[test]
fn test_backend_selector_extreme_parameters() {
let tiny_selector = BackendSelector::new()
.with_pcie_bandwidth(1e6) .with_gpu_gflops(1e9) .with_min_dispatch_ratio(1.0);
let backend = tiny_selector.select_backend(100, 1000);
assert!(backend == Backend::SIMD || backend == Backend::GPU);
let huge_selector = BackendSelector::new()
.with_pcie_bandwidth(1e12) .with_gpu_gflops(1e15) .with_min_dispatch_ratio(100.0);
let backend = huge_selector.select_backend(1_000_000_000, 1_000_000_000_000);
assert!(backend == Backend::SIMD || backend == Backend::GPU);
}
#[test]
fn test_select_backend_zero_data_edge() {
let selector = BackendSelector::new();
let backend = selector.select_backend(0, 1000);
assert_eq!(backend, Backend::GPU); }
#[test]
fn test_select_backend_zero_flops_edge() {
let selector = BackendSelector::new();
let backend = selector.select_backend(1000, 0);
assert_eq!(backend, Backend::SIMD);
}
#[test]
fn test_select_for_matmul_zero_edge() {
let selector = BackendSelector::new();
let backend = selector.select_for_matmul(0, 0, 0);
assert!(backend == Backend::SIMD || backend == Backend::GPU);
}
#[test]
fn test_select_for_elementwise_boundary_edge() {
let selector = BackendSelector::new();
let backend_small = selector.select_for_elementwise(1_000);
let backend_medium = selector.select_for_elementwise(500_000);
let backend_large = selector.select_for_elementwise(2_000_000);
assert_eq!(backend_small, Backend::Scalar);
assert_eq!(backend_large, Backend::SIMD);
assert!(backend_medium == Backend::Scalar || backend_medium == Backend::SIMD);
}
#[test]
fn test_moe_boundary_conditions_edge() {
let selector = BackendSelector::new();
let small = selector.select_with_moe(OpComplexity::Medium, 1_000);
let large = selector.select_with_moe(OpComplexity::Medium, 500_000);
assert_eq!(small, Backend::Scalar);
assert_eq!(large, Backend::GPU);
}