#![allow(clippy::ignore_without_reason, clippy::expect_used)]
use super::super::traits::MatMulOp;
use super::*;
#[test]
#[ignore]
fn test_selection_strategy_default() {
assert_eq!(SelectionStrategy::default(), SelectionStrategy::Automatic);
}
#[test]
#[ignore]
fn test_selection_strategy_threshold() {
let strategy = SelectionStrategy::threshold(1_000_000);
assert!(matches!(
strategy,
SelectionStrategy::Threshold {
min_flops: 1_000_000
}
));
}
#[test]
#[ignore]
fn test_selection_strategy_description() {
assert!(SelectionStrategy::PreferGpu.description().contains("GPU"));
assert!(SelectionStrategy::PreferSimd.description().contains("SIMD"));
assert!(SelectionStrategy::Automatic
.description()
.contains("automatic"));
}
#[test]
#[ignore]
fn test_selector_config_default() {
let config = SelectorConfig::default();
assert_eq!(config.strategy, SelectionStrategy::Automatic);
assert!(config.gpu_threshold_flops > 0);
}
#[test]
#[ignore]
fn test_selector_config_for_inference() {
let config = SelectorConfig::for_inference();
assert_eq!(config.strategy, SelectionStrategy::Automatic);
assert!(config.gpu_threshold_flops >= 1_000_000);
}
#[test]
#[ignore]
fn test_selector_config_builders() {
let config = SelectorConfig::default()
.with_strategy(SelectionStrategy::PreferGpu)
.with_gpu_threshold(500_000)
.with_max_gpu_memory(512 * 1024 * 1024);
assert_eq!(config.strategy, SelectionStrategy::PreferGpu);
assert_eq!(config.gpu_threshold_flops, 500_000);
assert_eq!(config.max_gpu_memory, 512 * 1024 * 1024);
}
#[test]
#[ignore]
fn test_backend_selector_new() {
let selector = BackendSelector::new(SelectorConfig::default());
assert!(selector.simd_capabilities().available);
}
#[test]
#[ignore]
fn test_backend_selector_default_config() {
let selector = BackendSelector::default_config();
assert!(selector.simd_capabilities().available);
}
#[test]
#[ignore]
fn test_backend_selector_select_prefer_simd() {
let selector = BackendSelector::new(SelectorConfig::prefer_simd());
let op = MatMulOp::new(64, 128, 64);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("PreferSimd"));
}
#[test]
#[ignore]
fn test_backend_selector_select_small_workload() {
let selector =
BackendSelector::new(SelectorConfig::default().with_gpu_threshold(1_000_000_000));
let op = MatMulOp::new(8, 8, 8); let selection = selector.select(&op);
assert!(selection.is_simd());
}
#[test]
#[ignore]
fn test_backend_selector_select_threshold() {
let selector = BackendSelector::new(
SelectorConfig::default().with_strategy(SelectionStrategy::threshold(100)),
);
let small_op = MatMulOp::new(2, 2, 2);
let selection = selector.select(&small_op);
assert!(selection.is_simd());
}
#[test]
#[ignore]
fn test_backend_selector_select_batch() {
let selector = BackendSelector::default_config();
let ops = vec![
MatMulOp::new(64, 128, 64),
MatMulOp::new(64, 128, 64),
MatMulOp::new(64, 128, 64),
];
let selection = selector.select_batch(&ops);
assert!(!selection.reason.is_empty());
}
#[test]
#[ignore]
fn test_backend_selector_select_batch_empty() {
let selector = BackendSelector::default_config();
let ops: Vec<MatMulOp> = vec![];
let selection = selector.select_batch(&ops);
assert!(selection.is_simd());
assert!(selection.reason.contains("No operations"));
}
#[test]
#[ignore]
fn test_backend_selector_summary() {
let selector = BackendSelector::default_config();
let summary = selector.summary();
assert!(summary.contains("SIMD"));
assert!(summary.contains("parallelism"));
}
#[test]
#[ignore]
fn test_backend_selection_gpu() {
let selection = BackendSelection::gpu("test reason");
assert!(selection.is_gpu());
assert!(!selection.is_simd());
assert_eq!(selection.reason, "test reason");
}
#[test]
#[ignore]
fn test_backend_selection_simd() {
let selection = BackendSelection::simd("test reason");
assert!(selection.is_simd());
assert!(!selection.is_gpu());
}
#[test]
#[ignore]
fn test_backend_selection_display() {
let selection = BackendSelection::gpu("performance");
let s = selection.to_string();
assert!(s.contains("GPU"));
assert!(s.contains("performance"));
}
#[test]
#[ignore]
fn test_selection_strategy_threshold_description() {
let strategy = SelectionStrategy::threshold(1_000_000);
assert_eq!(strategy.description(), "threshold-based");
}
#[test]
#[ignore]
fn test_selector_config_prefer_gpu() {
let config = SelectorConfig::prefer_gpu();
assert_eq!(config.strategy, SelectionStrategy::PreferGpu);
}
#[test]
#[ignore]
fn test_selector_config_prefer_simd() {
let config = SelectorConfig::prefer_simd();
assert_eq!(config.strategy, SelectionStrategy::PreferSimd);
}
#[test]
#[ignore]
fn test_backend_selector_config_accessor() {
let selector = BackendSelector::default_config();
let config = selector.config();
assert_eq!(config.strategy, SelectionStrategy::Automatic);
}
#[test]
#[ignore]
fn test_backend_selector_gpu_capabilities() {
let selector = BackendSelector::default_config();
let _ = selector.gpu_capabilities();
}
#[test]
#[ignore]
fn test_backend_selector_select_prefer_gpu_no_gpu() {
let selector = BackendSelector::new(SelectorConfig::prefer_gpu());
let op = MatMulOp::new(64, 128, 64);
let selection = selector.select(&op);
assert!(!selection.reason.is_empty());
}
#[test]
#[ignore]
fn test_backend_selector_select_large_workload() {
let selector = BackendSelector::new(SelectorConfig::default().with_gpu_threshold(100));
let op = MatMulOp::new(128, 256, 128); let selection = selector.select(&op);
assert!(!selection.reason.is_empty());
}
#[test]
#[ignore]
fn test_backend_selection_backend_type() {
let gpu_selection = BackendSelection::gpu("test");
assert_eq!(gpu_selection.backend, BackendType::Gpu);
let simd_selection = BackendSelection::simd("test");
assert_eq!(simd_selection.backend, BackendType::Simd);
}
#[test]
#[ignore]
fn test_selector_with_high_memory_requirement() {
let config = SelectorConfig::default().with_max_gpu_memory(1024);
let selector = BackendSelector::new(config);
let op = MatMulOp::new(1024, 1024, 1024);
let selection = selector.select(&op);
assert!(!selection.reason.is_empty());
}
#[test]
#[ignore]
fn test_selector_automatic_with_small_workload() {
let selector = BackendSelector::new(SelectorConfig::default());
let op = MatMulOp::new(4, 4, 4); let selection = selector.select(&op);
assert!(selection.is_simd());
}
#[test]
#[ignore]
fn test_selector_threshold_below_flops() {
let selector = BackendSelector::new(
SelectorConfig::default().with_strategy(SelectionStrategy::threshold(1_000_000_000)),
);
let op = MatMulOp::new(32, 32, 32); let selection = selector.select(&op);
assert!(selection.is_simd());
}
#[test]
#[ignore]
fn test_selection_strategy_all_descriptions() {
assert!(!SelectionStrategy::PreferGpu.description().is_empty());
assert!(!SelectionStrategy::PreferSimd.description().is_empty());
assert!(!SelectionStrategy::Automatic.description().is_empty());
assert!(!SelectionStrategy::threshold(1000).description().is_empty());
}
#[test]
#[ignore]
fn test_selector_config_with_all_builders() {
let config = SelectorConfig::default()
.with_strategy(SelectionStrategy::Automatic)
.with_gpu_threshold(500_000)
.with_max_gpu_memory(1024 * 1024 * 1024);
assert_eq!(config.strategy, SelectionStrategy::Automatic);
assert_eq!(config.gpu_threshold_flops, 500_000);
assert_eq!(config.max_gpu_memory, 1024 * 1024 * 1024);
}
#[test]
#[ignore]
fn test_backend_selector_select_batch_large() {
let selector = BackendSelector::default_config();
let ops: Vec<MatMulOp> = (0..10).map(|_| MatMulOp::new(128, 256, 128)).collect();
let selection = selector.select_batch(&ops);
assert!(!selection.reason.is_empty());
}
#[test]
#[ignore]
fn test_backend_selector_simd_capabilities() {
let selector = BackendSelector::default_config();
let caps = selector.simd_capabilities();
assert!(caps.available);
assert!(caps.max_parallelism > 0);
}
#[test]
#[ignore]
fn test_backend_selector_gpu_available() {
let selector = BackendSelector::default_config();
let _available = selector.gpu_available();
}
#[test]
#[ignore]
fn test_selector_prefer_gpu_memory_exceeds_limit() {
let config = SelectorConfig::prefer_gpu().with_max_gpu_memory(1);
let selector = BackendSelector::new(config);
let op = MatMulOp::new(1024, 1024, 1024); let selection = selector.select(&op);
if selector.gpu_available() {
assert!(
selection.reason.contains("Memory exceeds")
|| selection.reason.contains("GPU not available")
);
}
}
#[test]
#[ignore]
fn test_selector_threshold_with_large_memory() {
let config = SelectorConfig::default()
.with_strategy(SelectionStrategy::threshold(100))
.with_max_gpu_memory(1);
let selector = BackendSelector::new(config);
let op = MatMulOp::new(1024, 1024, 1024);
let selection = selector.select(&op);
assert!(!selection.reason.is_empty());
}
#[test]
#[ignore]
fn test_selector_automatic_large_workload() {
let config = SelectorConfig::default().with_gpu_threshold(10);
let selector = BackendSelector::new(config);
let op = MatMulOp::new(256, 512, 256); let selection = selector.select(&op);
assert!(!selection.reason.is_empty());
}
#[test]
#[ignore]
fn test_selector_is_gpu_worthwhile_below_threshold() {
let config = SelectorConfig::default().with_gpu_threshold(1_000_000_000);
let selector = BackendSelector::new(config);
let op = MatMulOp::new(8, 8, 8); let selection = selector.select(&op);
assert!(selection.is_simd());
}
#[test]
#[ignore]
fn test_selector_batch_with_varying_sizes() {
let selector = BackendSelector::default_config();
let ops = vec![
MatMulOp::new(8, 8, 8),
MatMulOp::new(128, 128, 128),
MatMulOp::new(64, 64, 64),
];
let selection = selector.select_batch(&ops);
assert!(!selection.reason.is_empty());
}
#[test]
#[ignore]
fn test_selector_summary_with_different_strategies() {
let configs = vec![
SelectorConfig::default(),
SelectorConfig::prefer_gpu(),
SelectorConfig::prefer_simd(),
SelectorConfig::for_inference(),
];
for config in configs {
let selector = BackendSelector::new(config);
let summary = selector.summary();
assert!(summary.contains("SIMD"));
}
}
#[test]
#[ignore]
fn test_select_automatic_gpu_worthwhile() {
let config = SelectorConfig::default().with_gpu_threshold(100);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(256, 256, 256); let selection = selector.select(&op);
assert!(selection.is_gpu());
assert!(selection.reason.contains("Large workload"));
}
#[test]
#[ignore]
fn test_select_automatic_small_workload_with_gpu() {
let config = SelectorConfig::default().with_gpu_threshold(1_000_000_000);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(4, 4, 4); let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("Small workload"));
}
#[test]
#[ignore]
fn test_select_automatic_memory_exceeds_with_gpu() {
let config = SelectorConfig::default().with_max_gpu_memory(1);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(256, 256, 256);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("Memory exceeds"));
}
#[test]
#[ignore]
fn test_select_prefer_gpu_with_gpu_available() {
let config = SelectorConfig::prefer_gpu();
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(64, 128, 64);
let selection = selector.select(&op);
assert!(selection.is_gpu());
assert!(selection.reason.contains("PreferGpu"));
}
#[test]
#[ignore]
fn test_select_prefer_gpu_memory_exceeds_with_gpu() {
let config = SelectorConfig::prefer_gpu().with_max_gpu_memory(1);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(256, 256, 256);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("Memory exceeds"));
}
#[test]
#[ignore]
fn test_select_threshold_gpu_above_threshold() {
let config = SelectorConfig::default().with_strategy(SelectionStrategy::threshold(100));
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(128, 128, 128);
let selection = selector.select(&op);
assert!(selection.is_gpu());
assert!(selection.reason.contains("FLOPs exceed"));
}
#[test]
#[ignore]
fn test_select_threshold_gpu_below_threshold() {
let config =
SelectorConfig::default().with_strategy(SelectionStrategy::threshold(1_000_000_000));
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(4, 4, 4);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("below threshold"));
}
#[test]
#[ignore]
fn test_select_threshold_memory_exceeds_with_gpu() {
let config = SelectorConfig::default()
.with_strategy(SelectionStrategy::threshold(1))
.with_max_gpu_memory(1);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(256, 256, 256);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("Memory exceeds"));
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_via_batch_with_gpu() {
let config = SelectorConfig::default().with_gpu_threshold(100);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let ops = vec![MatMulOp::new(128, 128, 128), MatMulOp::new(128, 128, 128)];
let selection = selector.select_batch(&ops);
assert!(selection.is_gpu());
}
#[test]
#[ignore]
fn test_gpu_caps_memory_limit_check() {
let config = SelectorConfig::default().with_gpu_threshold(1);
let selector = BackendSelector::with_simulated_gpu(config, 64); let op = MatMulOp::new(256, 256, 256); let selection = selector.select(&op);
assert!(!selection.reason.is_empty());
}
#[test]
#[ignore]
fn test_simulated_gpu_summary() {
let config = SelectorConfig::default();
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let summary = selector.summary();
assert!(summary.contains("GPU"));
assert!(summary.contains("f16=true"));
}
#[test]
#[ignore]
fn test_simulated_gpu_capabilities() {
let config = SelectorConfig::default();
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
assert!(selector.gpu_available());
let gpu_caps = selector
.gpu_capabilities()
.expect("GPU should be available");
assert!(gpu_caps.available);
assert!(gpu_caps.supports_f16);
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_gpu_caps_cannot_handle() {
let config = SelectorConfig::default().with_gpu_threshold(1); let selector = BackendSelector::with_simulated_gpu(config, 16); let op = MatMulOp::new(256, 256, 256);
let selection = selector.select(&op);
assert!(selection.is_simd());
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_below_flops_threshold() {
let config = SelectorConfig::default().with_gpu_threshold(u64::MAX);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(4, 4, 4); let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("Small workload"));
}
#[test]
#[ignore]
fn test_select_automatic_gpu_memory_boundary() {
let op = MatMulOp::new(16, 16, 16);
let mem = op.memory_requirement() as u64;
let config = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(mem);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let selection = selector.select(&op);
assert!(selection.is_gpu() || selection.is_simd()); }
#[test]
#[ignore]
fn test_select_batch_gpu_worthwhile() {
let config = SelectorConfig::default().with_gpu_threshold(1);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let ops = vec![MatMulOp::new(64, 64, 64), MatMulOp::new(64, 64, 64)];
let selection = selector.select_batch(&ops);
assert!(selection.is_gpu());
}
#[test]
#[ignore]
fn test_select_batch_gpu_memory_too_small() {
let config = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(1); let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let ops = vec![MatMulOp::new(256, 256, 256)];
let selection = selector.select_batch(&ops);
assert!(selection.is_simd());
}
#[test]
#[ignore]
fn test_selector_automatic_gpu_memory_exceeded() {
let config = SelectorConfig::default()
.with_strategy(SelectionStrategy::Automatic)
.with_max_gpu_memory(1);
let selector = BackendSelector::new(config);
let op = MatMulOp::new(256, 256, 256);
let selection = selector.select(&op);
assert!(selection.is_simd());
}
#[test]
#[ignore]
fn test_selector_prefer_gpu_without_gpu() {
let config = SelectorConfig::prefer_gpu();
let selector = BackendSelector::new(config);
if !selector.gpu_available() {
let op = MatMulOp::new(64, 64, 64);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("not available") || selection.reason.contains("SIMD"));
}
}
#[test]
#[ignore]
fn test_selector_threshold_high_flops() {
let config = SelectorConfig::default().with_strategy(SelectionStrategy::threshold(1));
let selector = BackendSelector::new(config);
let op = MatMulOp::new(128, 128, 128);
let selection = selector.select(&op);
assert!(!selection.reason.is_empty());
}
#[test]
#[ignore]
fn test_selector_for_inference_config() {
let config = SelectorConfig::for_inference();
let selector = BackendSelector::new(config);
let op = MatMulOp::new(8, 8, 8);
let selection = selector.select(&op);
assert!(!selection.reason.is_empty());
}
#[test]
#[ignore]
fn test_backend_selection_reason_non_empty() {
let sel_gpu = BackendSelection::gpu("test reason");
assert_eq!(sel_gpu.reason, "test reason");
assert!(sel_gpu.is_gpu());
assert!(!sel_gpu.is_simd());
let sel_simd = BackendSelection::simd("simd reason");
assert_eq!(sel_simd.reason, "simd reason");
assert!(sel_simd.is_simd());
assert!(!sel_simd.is_gpu());
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_flops_above_threshold_caps_pass() {
let config = SelectorConfig::default().with_gpu_threshold(100);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(64, 64, 64);
let selection = selector.select(&op);
assert!(selection.is_gpu());
assert!(selection.reason.contains("Large workload"));
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_flops_below_threshold_returns_false() {
let config = SelectorConfig::default().with_gpu_threshold(999_999_999);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(4, 4, 4);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("Small workload"));
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_caps_cannot_handle_returns_false() {
let config = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(1024 * 1024 * 1024); let selector = BackendSelector::with_simulated_gpu(config, 32);
let op = MatMulOp::new(64, 64, 64); let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("Small workload"));
}
#[test]
#[ignore]
fn test_select_automatic_no_gpu_available() {
let selector = BackendSelector::new(SelectorConfig::default());
if !selector.gpu_available() {
let op = MatMulOp::new(256, 256, 256);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(
selection.reason.contains("not available")
|| selection.reason.contains("Small workload")
);
}
}
#[test]
#[ignore]
fn test_select_automatic_memory_exceeds_limit() {
let config = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(1); let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(128, 128, 128);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("Memory exceeds"));
}
#[test]
#[ignore]
fn test_select_automatic_gpu_worthwhile_true() {
let config = SelectorConfig::default()
.with_gpu_threshold(10)
.with_max_gpu_memory(1024 * 1024 * 1024);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(128, 128, 128);
let selection = selector.select(&op);
assert!(selection.is_gpu());
assert!(selection.reason.contains("Large workload"));
}
#[test]
#[ignore]
fn test_select_automatic_gpu_worthwhile_false() {
let config = SelectorConfig::default()
.with_gpu_threshold(u64::MAX)
.with_max_gpu_memory(1024 * 1024 * 1024);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(2, 2, 2); let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("Small workload"));
}
#[test]
#[ignore]
fn test_summary_with_simulated_gpu_includes_gpu_line() {
let config = SelectorConfig::default();
let selector = BackendSelector::with_simulated_gpu(config, 256 * 1024 * 1024);
let summary = selector.summary();
assert!(summary.contains("Backend Selector"));
assert!(summary.contains("automatic"));
assert!(summary.contains("SIMD"));
assert!(summary.contains("GPU"));
assert!(summary.contains("parallelism="));
assert!(summary.contains("score="));
assert!(summary.contains("f16="));
}
#[test]
#[ignore]
fn test_summary_without_gpu_shows_not_available() {
let selector = BackendSelector::new(SelectorConfig::default());
if !selector.gpu_available() {
let summary = selector.summary();
assert!(summary.contains("not available"));
}
}
#[test]
#[ignore]
fn test_summary_with_different_strategy_names() {
let config = SelectorConfig::prefer_gpu();
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let summary = selector.summary();
assert!(summary.contains("prefer GPU"));
let config2 = SelectorConfig::prefer_simd();
let selector2 = BackendSelector::new(config2);
let summary2 = selector2.summary();
assert!(summary2.contains("prefer SIMD"));
let config3 = SelectorConfig::default().with_strategy(SelectionStrategy::threshold(1000));
let selector3 = BackendSelector::new(config3);
let summary3 = selector3.summary();
assert!(summary3.contains("threshold-based"));
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_zero_flops() {
let config = SelectorConfig::default().with_gpu_threshold(0);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(0, 0, 0);
let selection = selector.select(&op);
assert!(!selection.reason.is_empty());
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_flops_exactly_at_threshold() {
let config = SelectorConfig::default()
.with_gpu_threshold(100)
.with_max_gpu_memory(1024 * 1024 * 1024);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(10, 5, 1); let selection = selector.select(&op);
assert!(selection.is_gpu());
assert!(selection.reason.contains("Large workload"));
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_flops_one_below_threshold() {
let config = SelectorConfig::default()
.with_gpu_threshold(101)
.with_max_gpu_memory(1024 * 1024 * 1024);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(10, 5, 1); let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("Small workload"));
}
#[ignore]
#[test]
fn test_is_gpu_worthwhile_gpu_caps_none_not_available() {
let selector = BackendSelector::new(SelectorConfig::default());
assert!(!selector.gpu_available());
assert!(selector.gpu_capabilities().is_none());
let op = MatMulOp::new(256, 256, 256);
let selection = selector.select(&op);
assert!(selection.is_simd());
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_gpu_can_handle_exact_boundary() {
let op = MatMulOp::new(8, 8, 8);
let mem = op.memory_requirement();
assert_eq!(mem, 768);
let config = SelectorConfig::default()
.with_gpu_threshold(1) .with_max_gpu_memory(1024 * 1024 * 1024); let selector = BackendSelector::with_simulated_gpu(config, mem as u64);
let selection = selector.select(&op);
assert!(selection.is_gpu());
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_gpu_can_handle_one_byte_short() {
let op = MatMulOp::new(8, 8, 8);
let mem = op.memory_requirement();
let config = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(1024 * 1024 * 1024);
let selector = BackendSelector::with_simulated_gpu(config, (mem as u64) - 1);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("Small workload"));
}
#[test]
#[ignore]
fn test_backend_selector_new_default_config_fields() {
let config = SelectorConfig::default();
let selector = BackendSelector::new(config);
assert_eq!(selector.config().strategy, SelectionStrategy::Automatic);
assert_eq!(selector.config().gpu_threshold_flops, 100_000);
assert_eq!(selector.config().max_gpu_memory, 256 * 1024 * 1024);
assert_eq!(selector.config().gpu_dispatch_overhead_us, 100);
}
#[test]
#[ignore]
fn test_backend_selector_new_for_inference_config() {
let config = SelectorConfig::for_inference();
let selector = BackendSelector::new(config);
assert_eq!(selector.config().strategy, SelectionStrategy::Automatic);
assert_eq!(selector.config().gpu_threshold_flops, 1_000_000);
assert_eq!(selector.config().max_gpu_memory, 1024 * 1024 * 1024);
assert_eq!(selector.config().gpu_dispatch_overhead_us, 50);
}
#[test]
#[ignore]
fn test_backend_selector_new_simd_caps_always_available() {
let configs = vec![
SelectorConfig::default(),
SelectorConfig::prefer_gpu(),
SelectorConfig::prefer_simd(),
SelectorConfig::for_inference(),
];
for config in configs {
let selector = BackendSelector::new(config);
let caps = selector.simd_capabilities();
assert!(caps.available);
assert_eq!(caps.backend_type, BackendType::Simd);
assert!(caps.max_parallelism > 0);
assert!(caps.performance_score > 0.0);
}
}
#[test]
#[ignore]
fn test_select_with_softmax_op_prefer_simd() {
use super::super::traits::SoftmaxOp;
let selector = BackendSelector::new(SelectorConfig::prefer_simd());
let op = SoftmaxOp::new(32, 512);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("PreferSimd"));
}
#[test]
#[ignore]
fn test_select_with_softmax_op_automatic_gpu() {
use super::super::traits::SoftmaxOp;
let config = SelectorConfig::default()
.with_gpu_threshold(1_000)
.with_max_gpu_memory(1024 * 1024 * 1024);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = SoftmaxOp::new(1000, 1000);
let selection = selector.select(&op);
assert!(selection.is_gpu());
assert!(selection.reason.contains("Large workload"));
}
#[test]
#[ignore]
fn test_select_with_layer_norm_op_automatic_gpu() {
use super::super::traits::LayerNormOp;
let config = SelectorConfig::default()
.with_gpu_threshold(100_000)
.with_max_gpu_memory(1024 * 1024 * 1024);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = LayerNormOp::new(64, 1024);
let selection = selector.select(&op);
assert!(selection.is_gpu());
}
#[test]
#[ignore]
fn test_select_with_gelu_op_below_threshold() {
use super::super::traits::GeluOp;
let config = SelectorConfig::default()
.with_gpu_threshold(10_000)
.with_max_gpu_memory(1024 * 1024 * 1024);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = GeluOp::new(100);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("Small workload"));
}
#[test]
#[ignore]
fn test_select_with_gelu_op_above_threshold() {
use super::super::traits::GeluOp;
let config = SelectorConfig::default()
.with_gpu_threshold(500_000)
.with_max_gpu_memory(1024 * 1024 * 1024);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = GeluOp::new(100_000);
let selection = selector.select(&op);
assert!(selection.is_gpu());
}
#[test]
#[ignore]
fn test_select_prefer_gpu_gpu_available_memory_fits() {
let config = SelectorConfig::prefer_gpu().with_max_gpu_memory(1024 * 1024 * 1024);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(32, 32, 32);
let selection = selector.select(&op);
assert!(selection.is_gpu());
assert!(selection.reason.contains("PreferGpu strategy"));
}
#[test]
#[ignore]
fn test_select_prefer_gpu_gpu_available_memory_exceeds() {
let config = SelectorConfig::prefer_gpu().with_max_gpu_memory(1); let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(64, 64, 64); let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("Memory exceeds GPU limit"));
}
#[test]
#[ignore]
fn test_select_threshold_flops_exactly_at_min_flops() {
let config = SelectorConfig::default()
.with_strategy(SelectionStrategy::threshold(100))
.with_max_gpu_memory(1024 * 1024 * 1024);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(10, 5, 1); let selection = selector.select(&op);
assert!(selection.is_gpu());
assert!(selection.reason.contains("FLOPs exceed threshold"));
}
#[test]
#[ignore]
fn test_select_threshold_flops_one_below_min_flops() {
let config = SelectorConfig::default()
.with_strategy(SelectionStrategy::threshold(101))
.with_max_gpu_memory(1024 * 1024 * 1024);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(10, 5, 1); let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("below threshold"));
}
#[test]
#[ignore]
fn test_select_threshold_memory_exceeds_with_high_flops() {
let config = SelectorConfig::default()
.with_strategy(SelectionStrategy::threshold(1))
.with_max_gpu_memory(1); let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(256, 256, 256); let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("Memory exceeds GPU limit"));
}
#[ignore]
#[test]
fn test_select_threshold_no_gpu_available() {
let config = SelectorConfig::default().with_strategy(SelectionStrategy::threshold(1));
let selector = BackendSelector::new(config); let op = MatMulOp::new(256, 256, 256);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("GPU not available"));
}
#[test]
#[ignore]
fn test_select_automatic_gpu_available_memory_at_exact_limit() {
let op = MatMulOp::new(8, 8, 8);
let mem = op.memory_requirement() as u64;
let config = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(mem); let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let selection = selector.select(&op);
assert!(selection.is_gpu());
}
#[test]
#[ignore]
fn test_select_automatic_gpu_available_memory_one_over_limit() {
let op = MatMulOp::new(8, 8, 8);
let mem = op.memory_requirement() as u64;
let config = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(mem - 1); let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("Memory exceeds GPU limit"));
}
#[test]
#[ignore]
fn test_select_automatic_zero_memory_zero_flops() {
let config = SelectorConfig::default()
.with_gpu_threshold(0)
.with_max_gpu_memory(1024 * 1024 * 1024);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(0, 0, 0); let selection = selector.select(&op);
assert!(selection.is_gpu());
}
#[test]
#[ignore]
fn test_select_automatic_very_large_flops() {
let config = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(u64::MAX);
let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let op = MatMulOp::new(4096, 4096, 4096);
let selection = selector.select(&op);
assert!(selection.is_gpu());
assert!(selection.reason.contains("Large workload"));
}
#[test]
#[ignore]
fn test_select_batch_single_op() {
let config = SelectorConfig::default().with_gpu_threshold(1);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let ops = vec![MatMulOp::new(64, 64, 64)];
let selection = selector.select_batch(&ops);
assert!(selection.is_gpu());
}
#[test]
#[ignore]
fn test_select_batch_mixed_op_types_via_matmul() {
let config = SelectorConfig::default().with_gpu_threshold(1);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let ops = vec![
MatMulOp::new(1, 1, 1), MatMulOp::new(512, 512, 512), ];
let selection = selector.select_batch(&ops);
assert!(selection.is_gpu());
}
#[test]
#[ignore]
fn test_select_batch_all_tiny_ops_high_threshold() {
let config = SelectorConfig::default().with_gpu_threshold(u64::MAX);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let ops = vec![
MatMulOp::new(1, 1, 1),
MatMulOp::new(1, 1, 1),
MatMulOp::new(1, 1, 1),
];
let selection = selector.select_batch(&ops);
assert!(selection.is_simd());
}
#[test]
#[ignore]
fn test_select_batch_memory_exceeds_for_largest_op() {
let config = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(100); let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let ops = vec![
MatMulOp::new(2, 2, 2), MatMulOp::new(256, 256, 256), ];
let selection = selector.select_batch(&ops);
assert!(selection.is_simd());
assert!(selection.reason.contains("Memory exceeds"));
}
#[test]
#[ignore]
fn test_backend_selection_display_simd() {
let selection = BackendSelection::simd("CPU is faster for small workloads");
let display = format!("{selection}");
assert!(display.contains("SIMD"));
assert!(display.contains("CPU is faster for small workloads"));
}
#[test]
#[ignore]
fn test_backend_selection_clone() {
let selection = BackendSelection::gpu("cloneable");
let cloned = selection.clone();
assert_eq!(cloned.backend, BackendType::Gpu);
assert_eq!(cloned.reason, "cloneable");
}
#[test]
#[ignore]
fn test_selector_config_chained_builders_all_fields() {
let config = SelectorConfig::default()
.with_strategy(SelectionStrategy::threshold(42))
.with_gpu_threshold(999)
.with_max_gpu_memory(12345);
assert!(matches!(
config.strategy,
SelectionStrategy::Threshold { min_flops: 42 }
));
assert_eq!(config.gpu_threshold_flops, 999);
assert_eq!(config.max_gpu_memory, 12345);
}
#[test]
#[ignore]
fn test_selection_strategy_clone_and_copy() {
let s = SelectionStrategy::PreferGpu;
let s2 = s; let s3 = s; assert_eq!(s, s2);
assert_eq!(s, s3);
}
#[test]
#[ignore]
fn test_selection_strategy_debug_format() {
let s = SelectionStrategy::Threshold { min_flops: 500 };
let debug = format!("{s:?}");
assert!(debug.contains("Threshold"));
assert!(debug.contains("500"));
}
#[test]
#[ignore]
fn test_selection_strategy_eq_different_variants() {
assert_ne!(SelectionStrategy::PreferGpu, SelectionStrategy::PreferSimd);
assert_ne!(SelectionStrategy::Automatic, SelectionStrategy::PreferGpu);
assert_ne!(
SelectionStrategy::threshold(100),
SelectionStrategy::threshold(200)
);
assert_eq!(
SelectionStrategy::threshold(100),
SelectionStrategy::threshold(100)
);
}
#[test]
#[ignore]
#[allow(clippy::expect_used)]
fn test_with_simulated_gpu_fields() {
let config = SelectorConfig::default();
let selector = BackendSelector::with_simulated_gpu(config, 2048);
assert!(selector.gpu_available());
let gpu_caps = selector
.gpu_capabilities()
.expect("GPU should be available");
assert!(gpu_caps.available);
assert_eq!(gpu_caps.max_buffer_size, 2048);
assert_eq!(gpu_caps.max_parallelism, 256);
assert!(gpu_caps.supports_f16);
assert_eq!(gpu_caps.backend_type, BackendType::Gpu);
}
#[test]
#[ignore]
fn test_select_all_strategies_same_op() {
let op = MatMulOp::new(64, 128, 64);
let max_mem = 1024 * 1024 * 1024_u64;
let s1 = BackendSelector::with_simulated_gpu(SelectorConfig::prefer_gpu(), max_mem);
let r1 = s1.select(&op);
assert!(r1.is_gpu());
let s2 = BackendSelector::with_simulated_gpu(SelectorConfig::prefer_simd(), max_mem);
let r2 = s2.select(&op);
assert!(r2.is_simd());
let cfg3 = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(max_mem);
let s3 = BackendSelector::with_simulated_gpu(cfg3, max_mem);
let r3 = s3.select(&op);
assert!(r3.is_gpu());
let cfg4 = SelectorConfig::default()
.with_strategy(SelectionStrategy::threshold(u64::MAX))
.with_max_gpu_memory(max_mem);
let s4 = BackendSelector::with_simulated_gpu(cfg4, max_mem);
let r4 = s4.select(&op);
assert!(r4.is_simd());
}
#[test]
#[ignore]
fn test_select_automatic_transitions_based_on_workload_size() {
let max_mem = 1024 * 1024 * 1024_u64;
let threshold = 50_000_u64;
let config = SelectorConfig::default()
.with_gpu_threshold(threshold)
.with_max_gpu_memory(max_mem);
let selector = BackendSelector::with_simulated_gpu(config, max_mem);
let small_op = MatMulOp::new(4, 4, 4); let sel_small = selector.select(&small_op);
assert!(sel_small.is_simd());
let med_op = MatMulOp::new(30, 30, 30);
let sel_med = selector.select(&med_op);
assert!(sel_med.is_gpu());
}
#[ignore]
#[test]
fn test_prefer_gpu_no_gpu_falls_back_to_simd_reason() {
let selector = BackendSelector::new(SelectorConfig::prefer_gpu());
let op = MatMulOp::new(256, 256, 256);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("GPU not available"));
}
#[test]
#[ignore]
fn test_select_prefer_simd_ignores_gpu_even_if_available() {
let config = SelectorConfig::prefer_simd();
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
assert!(selector.gpu_available());
let op = MatMulOp::new(512, 512, 512); let selection = selector.select(&op);
assert!(selection.is_simd());
assert!(selection.reason.contains("PreferSimd strategy"));
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_path_flops_below_threshold() {
let config = SelectorConfig::default()
.with_gpu_threshold(10_000_000)
.with_max_gpu_memory(u64::MAX);
let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let op = MatMulOp::new(4, 4, 4);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "Small workload better on CPU");
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_path_can_handle_fails() {
let config = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(u64::MAX);
let selector = BackendSelector::with_simulated_gpu(config, 8);
let op = MatMulOp::new(16, 16, 16);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "Small workload better on CPU");
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_path_both_checks_pass() {
let config = SelectorConfig::default()
.with_gpu_threshold(100)
.with_max_gpu_memory(u64::MAX);
let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let op = MatMulOp::new(32, 32, 32);
let selection = selector.select(&op);
assert!(selection.is_gpu());
assert_eq!(selection.reason, "Large workload benefits from GPU");
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_no_gpu_caps_but_available() {
let simd_caps = BackendCapabilities::simd();
let config = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(u64::MAX);
let selector = BackendSelector {
config,
simd_caps,
gpu_available: true,
gpu_caps: None,
};
let op = MatMulOp::new(16, 16, 16);
let selection = selector.select(&op);
assert!(selection.is_gpu());
assert_eq!(selection.reason, "Large workload benefits from GPU");
}
#[ignore]
#[test]
fn test_new_no_gpu_stores_none_caps() {
let config = SelectorConfig::default();
let selector = BackendSelector::new(config);
assert!(!selector.gpu_available());
assert!(selector.gpu_capabilities().is_none());
let simd = selector.simd_capabilities();
assert!(simd.available);
assert_eq!(simd.backend_type, BackendType::Simd);
}
#[test]
#[ignore]
fn test_new_stores_custom_config() {
let config = SelectorConfig::default()
.with_strategy(SelectionStrategy::threshold(42_000))
.with_gpu_threshold(77_777)
.with_max_gpu_memory(99_999);
let selector = BackendSelector::new(config);
let stored = selector.config();
assert!(matches!(
stored.strategy,
SelectionStrategy::Threshold { min_flops: 42_000 }
));
assert_eq!(stored.gpu_threshold_flops, 77_777);
assert_eq!(stored.max_gpu_memory, 99_999);
}
#[ignore]
#[test]
fn test_new_prefer_gpu_config_no_webgpu() {
let selector = BackendSelector::new(SelectorConfig::prefer_gpu());
assert_eq!(selector.config().strategy, SelectionStrategy::PreferGpu);
assert!(!selector.gpu_available());
assert!(selector.gpu_capabilities().is_none());
let op = MatMulOp::new(64, 64, 64);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "GPU not available");
}
#[test]
#[ignore]
fn test_new_for_inference_fields() {
let selector = BackendSelector::new(SelectorConfig::for_inference());
let config = selector.config();
assert_eq!(config.strategy, SelectionStrategy::Automatic);
assert_eq!(config.gpu_threshold_flops, 1_000_000);
assert_eq!(config.max_gpu_memory, 1024 * 1024 * 1024);
assert_eq!(config.gpu_dispatch_overhead_us, 50);
assert!(selector.simd_capabilities().available);
}
#[test]
#[ignore]
fn test_select_prefer_gpu_arm_gpu_available_memory_ok() {
let config = SelectorConfig::prefer_gpu().with_max_gpu_memory(1024 * 1024 * 1024);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(16, 16, 16);
let selection = selector.select(&op);
assert!(selection.is_gpu());
assert_eq!(selection.reason, "PreferGpu strategy");
}
#[test]
#[ignore]
fn test_select_prefer_gpu_arm_memory_exceeds() {
let config = SelectorConfig::prefer_gpu().with_max_gpu_memory(4);
let selector = BackendSelector::with_simulated_gpu(config, 1024 * 1024 * 1024);
let op = MatMulOp::new(32, 32, 32);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "Memory exceeds GPU limit");
}
#[ignore]
#[test]
fn test_select_prefer_gpu_arm_no_gpu() {
let selector = BackendSelector::new(SelectorConfig::prefer_gpu());
let op = MatMulOp::new(32, 32, 32);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "GPU not available");
}
#[test]
#[ignore]
fn test_select_prefer_simd_arm_always_simd() {
let config = SelectorConfig::prefer_simd();
let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let op = MatMulOp::new(512, 512, 512);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "PreferSimd strategy");
}
#[test]
#[ignore]
fn test_select_threshold_arm_above_min_flops() {
let config = SelectorConfig::default()
.with_strategy(SelectionStrategy::threshold(500))
.with_max_gpu_memory(u64::MAX);
let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let op = MatMulOp::new(16, 16, 16);
let selection = selector.select(&op);
assert!(selection.is_gpu());
assert_eq!(selection.reason, "FLOPs exceed threshold");
}
#[test]
#[ignore]
fn test_select_threshold_arm_below_min_flops() {
let config = SelectorConfig::default()
.with_strategy(SelectionStrategy::threshold(100_000))
.with_max_gpu_memory(u64::MAX);
let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let op = MatMulOp::new(4, 4, 4);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "FLOPs below threshold");
}
#[ignore]
#[test]
fn test_select_threshold_arm_no_gpu() {
let config = SelectorConfig::default().with_strategy(SelectionStrategy::threshold(1));
let selector = BackendSelector::new(config);
let op = MatMulOp::new(128, 128, 128);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "GPU not available");
}
#[test]
#[ignore]
fn test_select_threshold_arm_memory_exceeds() {
let config = SelectorConfig::default()
.with_strategy(SelectionStrategy::threshold(1))
.with_max_gpu_memory(4);
let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let op = MatMulOp::new(64, 64, 64);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "Memory exceeds GPU limit");
}
#[test]
#[ignore]
fn test_select_automatic_arm_delegates() {
let config = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(u64::MAX);
let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let op = MatMulOp::new(32, 32, 32);
let selection = selector.select(&op);
assert!(selection.is_gpu());
assert_eq!(selection.reason, "Large workload benefits from GPU");
}
#[ignore]
#[test]
fn test_select_automatic_no_gpu_early_return() {
let selector = BackendSelector::new(SelectorConfig::default());
assert!(!selector.gpu_available());
let op = MatMulOp::new(256, 256, 256);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "GPU not available");
}
#[test]
#[ignore]
fn test_select_automatic_memory_exceeds_early_return() {
let config = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(16); let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let op = MatMulOp::new(32, 32, 32);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "Memory exceeds GPU limit");
}
#[test]
#[ignore]
fn test_select_automatic_gpu_worthwhile_returns_gpu() {
let config = SelectorConfig::default()
.with_gpu_threshold(50)
.with_max_gpu_memory(u64::MAX);
let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let op = MatMulOp::new(16, 16, 16); let selection = selector.select(&op);
assert!(selection.is_gpu());
assert_eq!(selection.reason, "Large workload benefits from GPU");
}
#[test]
#[ignore]
fn test_select_automatic_gpu_not_worthwhile_returns_simd() {
let config = SelectorConfig::default()
.with_gpu_threshold(1_000_000)
.with_max_gpu_memory(u64::MAX);
let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let op = MatMulOp::new(4, 4, 4); let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "Small workload better on CPU");
}
#[test]
#[ignore]
fn test_select_automatic_memory_at_exact_boundary() {
let op = MatMulOp::new(8, 8, 8);
let mem = op.memory_requirement() as u64;
let config = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(mem); let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let selection = selector.select(&op);
assert!(selection.is_gpu());
assert_eq!(selection.reason, "Large workload benefits from GPU");
}
#[test]
#[ignore]
fn test_select_automatic_memory_one_over_boundary() {
let op = MatMulOp::new(8, 8, 8);
let mem = op.memory_requirement() as u64;
let config = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(mem - 1); let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "Memory exceeds GPU limit");
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_returns_true_all_checks_pass() {
let config = SelectorConfig::default()
.with_gpu_threshold(500)
.with_max_gpu_memory(u64::MAX);
let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let op = MatMulOp::new(32, 32, 32);
let selection = selector.select(&op);
assert!(selection.is_gpu());
assert_eq!(selection.reason, "Large workload benefits from GPU");
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_returns_false_flops_below() {
let config = SelectorConfig::default()
.with_gpu_threshold(1_000_000)
.with_max_gpu_memory(u64::MAX);
let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let op = MatMulOp::new(2, 2, 2);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "Small workload better on CPU");
}
#[test]
#[ignore]
fn test_is_gpu_worthwhile_returns_false_can_handle_fails() {
let config = SelectorConfig::default()
.with_gpu_threshold(1) .with_max_gpu_memory(u64::MAX); let selector = BackendSelector::with_simulated_gpu(config, 4);
let op = MatMulOp::new(16, 16, 16);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "Small workload better on CPU");
}
#[ignore]
#[test]
fn test_select_automatic_path_gpu_not_available() {
let config = SelectorConfig::default();
let selector = BackendSelector::new(config);
let op = MatMulOp::new(128, 128, 128);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "GPU not available");
}
#[test]
#[ignore]
fn test_select_automatic_path_memory_exceeds() {
let config = SelectorConfig::default()
.with_gpu_threshold(1)
.with_max_gpu_memory(8); let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let op = MatMulOp::new(32, 32, 32);
let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "Memory exceeds GPU limit");
}
#[test]
#[ignore]
fn test_select_automatic_path_gpu_worthwhile() {
let config = SelectorConfig::default()
.with_gpu_threshold(100)
.with_max_gpu_memory(u64::MAX);
let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let op = MatMulOp::new(64, 64, 64); let selection = selector.select(&op);
assert!(selection.is_gpu());
assert_eq!(selection.reason, "Large workload benefits from GPU");
}
#[test]
#[ignore]
fn test_select_automatic_path_gpu_not_worthwhile() {
let config = SelectorConfig::default()
.with_gpu_threshold(10_000_000) .with_max_gpu_memory(u64::MAX);
let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let op = MatMulOp::new(4, 4, 4); let selection = selector.select(&op);
assert!(selection.is_simd());
assert_eq!(selection.reason, "Small workload better on CPU");
}
#[test]
#[ignore]
fn test_select_batch_exercises_select_automatic_gpu() {
let config = SelectorConfig::default()
.with_gpu_threshold(100)
.with_max_gpu_memory(u64::MAX);
let selector = BackendSelector::with_simulated_gpu(config, u64::MAX);
let ops = vec![MatMulOp::new(32, 32, 32), MatMulOp::new(64, 64, 64)];
let selection = selector.select_batch(&ops);
assert!(selection.is_gpu());
assert_eq!(selection.reason, "Large workload benefits from GPU");
}
#[ignore]
#[test]
fn test_new_covers_no_gpu_detection_path() {
let config = SelectorConfig::default();
let selector = BackendSelector::new(config);
let simd = selector.simd_capabilities();
assert!(simd.available);
assert!(simd.max_parallelism > 0);
assert!(simd.performance_score > 0.0);
assert!(!selector.gpu_available());
assert!(selector.gpu_capabilities().is_none());
assert_eq!(selector.config().strategy, SelectionStrategy::Automatic);
}
#[test]
#[ignore]
fn test_new_all_config_constructors() {
let s1 = BackendSelector::new(SelectorConfig::default());
assert_eq!(s1.config().strategy, SelectionStrategy::Automatic);
assert_eq!(s1.config().gpu_threshold_flops, 100_000);
let s2 = BackendSelector::new(SelectorConfig::for_inference());
assert_eq!(s2.config().strategy, SelectionStrategy::Automatic);
assert_eq!(s2.config().gpu_threshold_flops, 1_000_000);
assert_eq!(s2.config().gpu_dispatch_overhead_us, 50);
let s3 = BackendSelector::new(SelectorConfig::prefer_gpu());
assert_eq!(s3.config().strategy, SelectionStrategy::PreferGpu);
let s4 = BackendSelector::new(SelectorConfig::prefer_simd());
assert_eq!(s4.config().strategy, SelectionStrategy::PreferSimd);
let s5 = BackendSelector::new(
SelectorConfig::default().with_strategy(SelectionStrategy::threshold(42)),
);
assert!(matches!(
s5.config().strategy,
SelectionStrategy::Threshold { min_flops: 42 }
));
}
#[test]
#[ignore]
#[allow(clippy::expect_used)]
fn test_simulated_gpu_covers_gpu_caps_construction() {
let config = SelectorConfig::for_inference();
let buffer_size = 512 * 1024 * 1024_u64;
let selector = BackendSelector::with_simulated_gpu(config, buffer_size);
assert!(selector.gpu_available());
let gpu = selector
.gpu_capabilities()
.expect("GPU caps should be present");
assert!(gpu.available);
assert_eq!(gpu.max_buffer_size, buffer_size);
assert!(gpu.supports_f16);
assert_eq!(gpu.backend_type, BackendType::Gpu);
assert!(selector.simd_capabilities().available);
assert_eq!(selector.config().strategy, SelectionStrategy::Automatic);
assert_eq!(selector.config().gpu_threshold_flops, 1_000_000);
}
#[test]
#[ignore]
fn test_new_preserves_custom_config_after_gpu_detection() {
let config = SelectorConfig::default()
.with_strategy(SelectionStrategy::threshold(99_999))
.with_gpu_threshold(12_345)
.with_max_gpu_memory(67_890);
let selector = BackendSelector::new(config);
let stored = selector.config();
assert!(matches!(
stored.strategy,
SelectionStrategy::Threshold { min_flops: 99_999 }
));
assert_eq!(stored.gpu_threshold_flops, 12_345);
assert_eq!(stored.max_gpu_memory, 67_890);
}
#[test]
#[ignore]
fn test_new_zero_threshold_config() {
let config = SelectorConfig::default()
.with_gpu_threshold(0)
.with_max_gpu_memory(0);
let selector = BackendSelector::new(config);
assert_eq!(selector.config().gpu_threshold_flops, 0);
assert_eq!(selector.config().max_gpu_memory, 0);
let op = MatMulOp::new(4, 4, 4);
let selection = selector.select(&op);
assert!(!selection.reason.is_empty());
}
#[test]
#[ignore]
fn test_new_then_summary_exercises_constructor() {
let selector = BackendSelector::new(SelectorConfig::default());
let summary = selector.summary();
assert!(summary.contains("automatic"));
assert!(summary.contains("SIMD"));
if !selector.gpu_available() {
assert!(summary.contains("not available"));
}
}