mod common;
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use single_svdlib::{irlba, randomized, MaskedCsMat, SparseMatDense};
use std::hint::black_box;
use std::time::Duration;
fn fixture() -> single_svdlib::SvdMat<f64> {
common::counts(15_000, 1_500, 80, 16, 7)
}
fn irlba_ranks(c: &mut Criterion) {
let a = fixture();
let mut group = c.benchmark_group("irlba");
group
.sample_size(10)
.measurement_time(Duration::from_secs(20));
for rank in [10usize, 30] {
group.bench_with_input(BenchmarkId::new("plain", rank), &rank, |b, &rank| {
b.iter(|| black_box(irlba::svd_seed(&a, rank, 42).unwrap()))
});
group.bench_with_input(BenchmarkId::new("centered", rank), &rank, |b, &rank| {
b.iter(|| black_box(irlba::svd_centered(&a, rank, Some(42)).unwrap()))
});
}
group.finish();
}
fn irlba_work(c: &mut Criterion) {
let a = fixture();
let rank = 30usize;
let means = a.col_means();
let mut group = c.benchmark_group("irlba_work");
group
.sample_size(10)
.measurement_time(Duration::from_secs(20));
let mut widths = vec![rank + 7, rank + 30, 2 * rank];
widths.sort_unstable();
widths.dedup();
for work in widths {
group.bench_with_input(BenchmarkId::from_parameter(work), &work, |b, &work| {
b.iter(|| {
black_box(
irlba::svd_with(
&a,
&irlba::IrlbaConfig::new(rank)
.seed(42)
.work(work)
.mean_center(true),
Some(means.clone()),
)
.unwrap(),
)
})
});
}
group.finish();
}
fn randomized_sketches(c: &mut Criterion) {
let a = fixture();
let rank = 30usize;
let mut group = c.benchmark_group("randomized");
group
.sample_size(10)
.measurement_time(Duration::from_secs(20));
for q in [2usize, 4] {
group.bench_with_input(BenchmarkId::new("power", q), &q, |b, &q| {
b.iter(|| {
black_box(
randomized::svd_with(
&a,
&randomized::RandomizedConfig::new(rank)
.seed(42)
.power_iterations(q),
None,
)
.unwrap(),
)
})
});
}
group.bench_function("block_krylov/2", |b| {
b.iter(|| black_box(randomized::svd_block_krylov(&a, rank, 2, Some(42)).unwrap()))
});
group.finish();
}
fn masked_pca(c: &mut Criterion) {
let a = fixture();
let selected = common::every_nth(a.cols(), 6);
let view = MaskedCsMat::with_columns(&a, &selected);
let extracted = view.to_sparse();
let rank = 20usize;
let mut group = c.benchmark_group("masked_pca");
group
.sample_size(10)
.measurement_time(Duration::from_secs(20));
group.bench_function("view", |b| {
b.iter(|| black_box(irlba::svd_centered(&view, rank, Some(42)).unwrap()))
});
group.bench_function("extracted", |b| {
b.iter(|| black_box(irlba::svd_centered(&extracted, rank, Some(42)).unwrap()))
});
group.bench_function("extract_then_solve", |b| {
b.iter(|| {
let sub = view.to_sparse();
black_box(irlba::svd_centered(&sub, rank, Some(42)).unwrap())
})
});
group.finish();
}
criterion_group!(
benches,
irlba_ranks,
irlba_work,
randomized_sketches,
masked_pca
);
criterion_main!(benches);