#![allow(deprecated)]
#![allow(clippy::result_large_err)]
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use numrs2::array::Array;
use numrs2::array_ops;
use numrs2::blas;
use numrs2::linalg;
use numrs2::math;
use numrs2::prelude::*;
use numrs2::random::distributions::*;
use numrs2::random::state::RandomState;
use numrs2::stats::Statistics;
use numrs2::unique::unique;
use std::hint::black_box;
use std::time::Duration;
struct BenchmarkConfig {
pub name: &'static str,
pub sizes: Vec<usize>,
pub iterations: usize,
}
impl Default for BenchmarkConfig {
fn default() -> Self {
Self {
name: "default",
sizes: vec![100, 1000, 10000, 100000],
iterations: 100,
}
}
}
fn generate_test_data_f64(size: usize) -> Vec<f64> {
let mut rng = RandomState::new();
(0..size)
.map(|_| rng.uniform(0.0, 1.0, &[1]).unwrap().get(&[0]).unwrap())
.collect()
}
fn generate_test_data_i32(size: usize) -> Vec<i32> {
let mut rng = RandomState::new();
(0..size)
.map(|_| (rng.uniform(0.0, 1000.0, &[1]).unwrap().get(&[0]).unwrap() as i32))
.collect()
}
fn bench_array_creation(c: &mut Criterion) {
let mut group = c.benchmark_group("array_creation");
let sizes = vec![1000, 10000, 100000, 1000000];
for size in sizes {
group.bench_with_input(BenchmarkId::new("zeros", size), &size, |b, &size| {
b.iter(|| {
let arr = Array::<f64>::zeros(&[size]);
black_box(arr)
})
});
group.bench_with_input(BenchmarkId::new("ones", size), &size, |b, &size| {
b.iter(|| {
let arr = Array::<f64>::ones(&[size]);
black_box(arr)
})
});
group.bench_with_input(BenchmarkId::new("from_vec", size), &size, |b, &size| {
let data = generate_test_data_f64(size);
b.iter(|| {
let arr = Array::from_vec(data.clone());
black_box(arr)
})
});
group.bench_with_input(BenchmarkId::new("arange", size), &size, |b, &size| {
b.iter(|| {
let arr = numrs2::math::arange(0.0, size as f64, 1.0);
black_box(arr)
})
});
}
group.finish();
}
fn bench_arithmetic_operations(c: &mut Criterion) {
let mut group = c.benchmark_group("arithmetic_operations");
let sizes = vec![1000, 10000, 100000];
for size in sizes {
let data1 = generate_test_data_f64(size);
let data2 = generate_test_data_f64(size);
let arr1 = Array::from_vec(data1);
let arr2 = Array::from_vec(data2);
group.bench_with_input(BenchmarkId::new("add", size), &size, |b, _| {
b.iter(|| {
let result = numrs2::ufuncs::add(&arr1, &arr2).unwrap();
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("subtract", size), &size, |b, _| {
b.iter(|| {
let result = numrs2::ufuncs::subtract(&arr1, &arr2).unwrap();
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("multiply", size), &size, |b, _| {
b.iter(|| {
let result = numrs2::ufuncs::multiply(&arr1, &arr2).unwrap();
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("divide", size), &size, |b, _| {
b.iter(|| {
let result = numrs2::ufuncs::divide(&arr1, &arr2).unwrap();
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("add_scalar", size), &size, |b, _| {
b.iter(|| {
let result = arr1.add_scalar(2.5);
black_box(result)
})
});
}
group.finish();
}
fn bench_mathematical_functions(c: &mut Criterion) {
let mut group = c.benchmark_group("mathematical_functions");
let sizes = vec![1000, 10000, 100000];
for size in sizes {
let data = generate_test_data_f64(size);
let arr = Array::from_vec(data);
group.bench_with_input(BenchmarkId::new("sqrt", size), &size, |b, _| {
b.iter(|| {
let result = numrs2::ufuncs::sqrt(&arr);
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("exp", size), &size, |b, _| {
b.iter(|| {
let result = numrs2::ufuncs::exp(&arr);
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("log", size), &size, |b, _| {
let positive_data: Vec<f64> = (0..size).map(|i| (i + 1) as f64).collect();
let positive_arr = Array::from_vec(positive_data);
b.iter(|| {
let result = numrs2::ufuncs::log(&positive_arr);
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("sin", size), &size, |b, _| {
b.iter(|| {
let result = numrs2::ufuncs::sin(&arr);
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("cos", size), &size, |b, _| {
b.iter(|| {
let result = numrs2::ufuncs::cos(&arr);
black_box(result)
})
});
}
group.finish();
}
fn bench_array_manipulation(c: &mut Criterion) {
let mut group = c.benchmark_group("array_manipulation");
let sizes = vec![100, 1000, 10000];
for size in sizes {
let data = generate_test_data_f64(size * size);
let arr = Array::from_vec(data).reshape(&[size, size]);
group.bench_with_input(BenchmarkId::new("transpose", size), &size, |b, _| {
b.iter(|| {
let result = arr.transpose();
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("reshape", size), &size, |b, _| {
b.iter(|| {
let result = arr.reshape(&[size / 2, size * 2]);
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("flatten", size), &size, |b, _| {
b.iter(|| {
let result = arr.flatten(None);
black_box(result)
})
});
}
group.finish();
}
fn bench_statistical_operations(c: &mut Criterion) {
let mut group = c.benchmark_group("statistical_operations");
let sizes = vec![1000, 10000, 100000];
for size in sizes {
let data = generate_test_data_f64(size);
let arr = Array::from_vec(data);
group.bench_with_input(BenchmarkId::new("sum", size), &size, |b, _| {
b.iter(|| {
let result = arr.sum();
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("mean", size), &size, |b, _| {
b.iter(|| {
let result = arr.mean();
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("std", size), &size, |b, _| {
b.iter(|| {
let result = arr.std();
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("var", size), &size, |b, _| {
b.iter(|| {
let result = arr.var();
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("min", size), &size, |b, _| {
b.iter(|| {
let result = arr.min();
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("max", size), &size, |b, _| {
b.iter(|| {
let result = arr.max();
black_box(result)
})
});
}
group.finish();
}
fn bench_linear_algebra(c: &mut Criterion) {
let mut group = c.benchmark_group("linear_algebra");
group.sample_size(20);
let sizes = vec![50, 100, 200, 500];
for size in sizes {
let data1 = generate_test_data_f64(size * size);
let data2 = generate_test_data_f64(size * size);
let mat1 = Array::from_vec(data1).reshape(&[size, size]);
let mat2 = Array::from_vec(data2).reshape(&[size, size]);
group.bench_with_input(BenchmarkId::new("matmul", size), &size, |b, _| {
b.iter(|| {
let result = mat1.matmul(&mat2).unwrap();
black_box(result)
})
});
if size <= 200 {
group.bench_with_input(BenchmarkId::new("inv", size), &size, |b, _| {
b.iter(|| {
})
});
}
if size <= 200 {
group.bench_with_input(BenchmarkId::new("det", size), &size, |b, _| {
b.iter(|| {
})
});
}
if size <= 100 {
group.bench_with_input(BenchmarkId::new("eig", size), &size, |b, _| {
b.iter(|| {
let result = eig_general(&mat1).unwrap();
black_box(result)
})
});
}
}
group.finish();
}
fn bench_sorting_searching(c: &mut Criterion) {
let mut group = c.benchmark_group("sorting_searching");
let sizes = vec![1000, 10000, 100000];
for size in sizes {
let data = generate_test_data_i32(size);
let arr = Array::from_vec(data);
group.bench_with_input(BenchmarkId::new("sort", size), &size, |b, _| {
b.iter(|| {
let result = arr.clone(); black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("argsort", size), &size, |b, _| {
b.iter(|| {
let result = arr.clone(); black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("unique", size), &size, |b, _| {
b.iter(|| {
let result = unique(&arr, None, None, None, None).unwrap();
black_box(result)
})
});
}
group.finish();
}
fn bench_memory_optimization(c: &mut Criterion) {
let mut group = c.benchmark_group("memory_optimization");
let sizes = vec![1000, 10000, 100000];
for size in sizes {
let data = generate_test_data_f64(size);
let arr = Array::from_vec(data);
group.bench_with_input(BenchmarkId::new("is_c_contiguous", size), &size, |b, _| {
b.iter(|| {
let result = arr.is_c_contiguous();
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("to_c_layout", size), &size, |b, _| {
b.iter(|| {
let result = arr.to_c_layout();
black_box(result)
})
});
}
group.finish();
}
fn bench_simd_operations(c: &mut Criterion) {
let mut group = c.benchmark_group("simd_operations");
let sizes = vec![1000, 10000, 100000, 1000000];
for size in sizes {
let data1 = generate_test_data_f64(size);
let data2 = generate_test_data_f64(size);
let arr1 = Array::from_vec(data1);
let arr2 = Array::from_vec(data2);
group.bench_with_input(BenchmarkId::new("simd_add", size), &size, |b, _| {
b.iter(|| {
let result = numrs2::ufuncs::add(&arr1, &arr2).unwrap();
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("simd_multiply", size), &size, |b, _| {
b.iter(|| {
let result = numrs2::ufuncs::multiply(&arr1, &arr2).unwrap();
black_box(result)
})
});
group.bench_with_input(BenchmarkId::new("dot_product", size), &size, |b, _| {
b.iter(|| {
let result = blas::dot(&arr1, &arr2).unwrap();
black_box(result)
})
});
}
group.finish();
}
criterion_group! {
name = numpy_comparison_benches;
config = Criterion::default()
.measurement_time(Duration::from_secs(10))
.sample_size(50);
targets =
bench_array_creation,
bench_arithmetic_operations,
bench_mathematical_functions,
bench_array_manipulation,
bench_statistical_operations,
bench_linear_algebra,
bench_sorting_searching,
bench_memory_optimization,
bench_simd_operations
}
criterion_main!(numpy_comparison_benches);