use scirs2_core::ndarray::Array2;
use scirs2_core::Complex64;
use scirs2_fft::{
fft2, get_global_planner, init_global_planner, plan_ahead_of_time, FftPlanExecutor,
PlanBuilder, PlanningConfig, PlanningStrategy,
};
use std::time::{Duration, Instant};
#[allow(dead_code)]
fn main() {
println!("FFT Plan Optimization Example");
println!("============================\n");
let config = PlanningConfig {
strategy: PlanningStrategy::CacheFirst,
measure_performance: true,
serialized_db_path: Some("./fft_plans.json".to_string()),
max_cached_plans: 256,
max_plan_age: Duration::from_secs(7200), ..Default::default()
};
let _ = init_global_planner(config);
println!("Planning ahead for common FFT sizes...");
let commonsizes = [128, 256, 512, 1024, 2048];
plan_ahead_of_time(&commonsizes, Some("./fft_plans.json")).expect("Operation failed");
println!("Creating test arrays...");
let n = 512;
let mut test_array = Array2::zeros((n, n));
test_array[[n / 4, n / 4]] = Complex64::new(1.0, 0.0);
println!("Performing standard FFT (will create plans on demand)...");
let start = Instant::now();
let result1 = fft2(&test_array, None, None, None).expect("Operation failed");
let std_time = start.elapsed();
println!("Standard FFT completed in {std_time:?}");
println!("\nTrying different planning strategies:");
let builder = PlanBuilder::new()
.shape(&[n, n])
.forward(true)
.strategy(PlanningStrategy::AlwaysNew);
let start = Instant::now();
let plan = builder.build().expect("Operation failed");
let plan_time = start.elapsed();
println!("1. PlanningStrategy::AlwaysNew");
println!(" Plan creation took: {plan_time:?}");
let executor = FftPlanExecutor::new(plan);
let mut result2_data = vec![Complex64::default(); n * n];
let input_flat: Vec<Complex64> = test_array.iter().cloned().collect();
let start = Instant::now();
executor
.execute(&input_flat, &mut result2_data)
.expect("Operation failed");
let exec_time = start.elapsed();
println!(" Plan execution took: {exec_time:?}");
println!(" Total time: {:?}", plan_time + exec_time);
let builder = PlanBuilder::new()
.shape(&[n, n])
.forward(true)
.strategy(PlanningStrategy::CacheFirst);
let start = Instant::now();
let plan = builder.build().expect("Operation failed");
let plan_time = start.elapsed();
println!("\n2. PlanningStrategy::CacheFirst");
println!(" Plan lookup/creation took: {plan_time:?}");
let executor = FftPlanExecutor::new(plan);
let mut result3_data = vec![Complex64::default(); n * n];
let start = Instant::now();
executor
.execute(&input_flat, &mut result3_data)
.expect("Operation failed");
let exec_time = start.elapsed();
println!(" Plan execution took: {exec_time:?}");
println!(" Total time: {:?}", plan_time + exec_time);
println!("\n3. Using the global planner (second run, should be cached)");
let planner = get_global_planner();
let start = Instant::now();
let plan = {
let mut planner_guard = planner.lock().expect("Operation failed");
planner_guard
.plan_fft(&[n, n], true, Default::default())
.expect("Operation failed")
};
let plan_time = start.elapsed();
println!(" Plan lookup took: {plan_time:?}");
let executor = FftPlanExecutor::new(plan);
let mut result4_data = vec![Complex64::default(); n * n];
let start = Instant::now();
executor
.execute(&input_flat, &mut result4_data)
.expect("Operation failed");
let exec_time = start.elapsed();
println!(" Plan execution took: {exec_time:?}");
println!(" Total time: {:?}", plan_time + exec_time);
println!("\nVerifying results...");
let result2_flat = &result2_data[0..10]; let result3_flat = &result3_data[0..10];
let result4_flat = &result4_data[0..10];
let result1_flat: Vec<Complex64> = result1.iter().take(10).cloned().collect();
println!("First 10 elements from standard FFT: {result1_flat:?}");
println!("First 10 elements from AlwaysNew: {result2_flat:?}");
println!("First 10 elements from CacheFirst: {result3_flat:?}");
println!("First 10 elements from global planner: {result4_flat:?}");
println!("\nPerformance comparison:");
println!("Standard FFT: {std_time:?}");
println!("AlwaysNew + execution: {:?}", plan_time + exec_time);
println!("Cached + execution: {:?}", plan_time + exec_time);
println!("\nDone!");
}