use scirs2_core::ndarray::{Array1, Array2};
#[cfg(feature = "scirs")]
use numrs2::optimized_ops::{
enhanced_exp, enhanced_math, get_optimization_info, process_large_array, simd_matmul,
SimdMathOps,
};
use std::time::Instant;
fn benchmark_operation<F>(name: &str, size: usize, iterations: usize, mut op: F) -> f64
where
F: FnMut(),
{
for _ in 0..5 {
op();
}
let start = Instant::now();
for _ in 0..iterations {
op();
}
let duration = start.elapsed();
let ops_per_sec = (iterations as f64 * size as f64) / duration.as_secs_f64();
println!("{:<40} {:>15.2} ops/sec", name, ops_per_sec);
ops_per_sec
}
#[allow(dead_code)]
fn benchmark_trigonometric_functions() {
println!("\n=== Trigonometric Function Benchmarks ===");
let sizes = vec![100, 1000, 10000, 100000];
for &size in &sizes {
println!("\nArray size: {}", size);
let data = Array1::from_vec((0..size).map(|x| x as f64 * 0.01).collect::<Vec<_>>());
let data_view = data.view();
let std_ops = benchmark_operation("Standard sin (scalar)", size, 100, || {
let _ = data_view.map(|&x| x.sin());
});
#[cfg(feature = "scirs")]
let par_ops = benchmark_operation("Parallel sin", size, 100, || {
let _ = enhanced_math::parallel_sin(&data_view);
});
#[cfg(feature = "scirs")]
println!("Speedup: {:.2}x", par_ops / std_ops);
}
}
#[allow(dead_code)]
fn benchmark_exponential_functions() {
println!("\n=== Exponential Function Benchmarks ===");
let sizes = vec![100, 1000, 10000, 100000];
for &size in &sizes {
println!("\nArray size: {}", size);
let data = Array1::from_vec(
(0..size)
.map(|x| (x as f64 * 0.01).min(10.0))
.collect::<Vec<_>>(),
);
let data_view = data.view();
let std_ops = benchmark_operation("Standard sqrt (scalar)", size, 100, || {
let _ = data_view.map(|&x| x.sqrt());
});
#[cfg(feature = "scirs")]
let simd_ops = benchmark_operation("SIMD sqrt", size, 100, || {
let _ = enhanced_exp::simd_sqrt(&data_view);
});
#[cfg(feature = "scirs")]
println!("Speedup: {:.2}x", simd_ops / std_ops);
}
}
#[allow(dead_code)]
fn benchmark_matrix_operations() {
println!("\n=== Matrix Operation Benchmarks ===");
let sizes = vec![10, 50, 100, 200];
for &size in &sizes {
println!("\nMatrix size: {}x{}", size, size);
let a = Array2::from_shape_vec(
(size, size),
(0..size * size)
.map(|x| x as f32 * 0.01)
.collect::<Vec<_>>(),
)
.unwrap();
let b = Array2::from_shape_vec(
(size, size),
(0..size * size)
.map(|x| x as f32 * 0.02)
.collect::<Vec<_>>(),
)
.unwrap();
let a_view = a.view();
let b_view = b.view();
let std_ops = benchmark_operation("Standard matmul", size * size, 10, || {
let _ = a.dot(&b);
});
#[cfg(feature = "scirs")]
let simd_ops = benchmark_operation("SIMD matmul", size * size, 10, || {
let _ = simd_matmul(&a_view, &b_view);
});
#[cfg(feature = "scirs")]
println!("Speedup: {:.2}x", simd_ops / std_ops);
}
}
#[allow(dead_code)]
fn benchmark_large_array_processing() {
println!("\n=== Large Array Processing Benchmarks ===");
let size = 1_000_000;
let chunk_sizes = vec![1000, 10000, 100000];
let data = Array1::from_vec((0..size).map(|x| x as f64 * 0.001).collect::<Vec<_>>());
let data_view = data.view();
println!("\nProcessing {} elements", size);
let std_time = {
let start = Instant::now();
let _ = data_view.map(|&x| x.sin() + x.cos());
start.elapsed().as_secs_f64()
};
println!("Standard processing: {:.3} seconds", std_time);
#[cfg(feature = "scirs")]
for &chunk_size in &chunk_sizes {
let chunked_time = {
let start = Instant::now();
let _ = process_large_array(&data_view, chunk_size, |chunk| {
chunk.map(|&x| x.sin() + x.cos())
});
start.elapsed().as_secs_f64()
};
println!(
"Chunked processing (chunk_size={}): {:.3} seconds (speedup: {:.2}x)",
chunk_size,
chunked_time,
std_time / chunked_time
);
}
}
#[allow(dead_code)]
fn benchmark_adaptive_algorithms() {
println!("\n=== Adaptive Algorithm Benchmarks ===");
let sizes = vec![10, 100, 1000, 10000, 100000];
println!("\nTesting adaptive algorithm selection for sqrt:");
#[cfg(feature = "scirs")]
for &size in &sizes {
let data = Array1::from_vec((0..size).map(|x| (x + 1) as f64).collect::<Vec<_>>());
let data_view = data.view();
let time = {
let start = Instant::now();
let _ = SimdMathOps::adaptive_math_function(&data_view, enhanced_exp::simd_sqrt, |x| {
x.sqrt()
});
start.elapsed()
};
println!(
"Size: {:>6} - Time: {:>8.3} ms - Rate: {:>10.2} Mops/sec",
size,
time.as_secs_f64() * 1000.0,
(size as f64) / time.as_secs_f64() / 1_000_000.0
);
}
}
fn main() {
println!("NumRS2 Performance Benchmark");
println!("============================");
#[cfg(feature = "scirs")]
{
println!("\n{}", get_optimization_info());
benchmark_trigonometric_functions();
benchmark_exponential_functions();
benchmark_matrix_operations();
benchmark_large_array_processing();
benchmark_adaptive_algorithms();
println!("\n=== Summary ===");
println!("The benchmarks demonstrate significant performance improvements when using:");
println!("- Parallel processing for trigonometric functions");
println!("- SIMD operations for mathematical functions");
println!("- Optimized matrix multiplication");
println!("- Chunked processing for memory efficiency");
println!("- Adaptive algorithm selection based on data size");
}
#[cfg(not(feature = "scirs"))]
{
println!("\nNote: This example requires the 'scirs' feature to be enabled.");
println!("Run with: cargo run --example performance_benchmark --features scirs");
}
}