Skip to content

Commit

Permalink
benches created for sparsemat#296
Browse files Browse the repository at this point in the history
  • Loading branch information
aujxn committed Apr 22, 2022
1 parent 25e35d2 commit c1f0129
Show file tree
Hide file tree
Showing 17 changed files with 378,400 additions and 54 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ approx = { version = "0.5", optional = true }
[dev-dependencies]
num-derive = "0.3"
bencher = "0.1.0"
criterion = "0.3.5"
tempfile = "3.1.0"
bincode = "1.2.0"
tobj = "3.0"
image = { version = "0.23.0", default-features = false, features = ["png"] }
rand = { version = "0.8", default-features = false, features = ["small_rng"] }
rand_xoshiro = "0.6.0"

[[bench]]
name = "suite"
Expand Down
225 changes: 171 additions & 54 deletions benches/sparse_dense_products.rs
Original file line number Diff line number Diff line change
@@ -1,63 +1,180 @@
use bencher::{benchmark_group, benchmark_main, Bencher};
use ndarray::{Array, Array2, ShapeBuilder};
use sprs::{CsMat, CsVec};

fn sparse_dense_dotprod_default(bench: &mut Bencher) {
let w = Array::range(0., 10., 0.00001);
let x = CsVec::new(1000000, vec![0, 200000, 800000], vec![1., 2., 3.]);
bench.iter(|| {
x.dot(&w);
});
use criterion::{
criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup,
BenchmarkId, Criterion,
};
use ndarray::Array2;
use rand::Rng;
use rand_xoshiro::rand_core::SeedableRng;
use rand_xoshiro::Xoshiro256Plus;
use sprs::CsMat;

fn generate_random_array(
shape: sprs::Shape,
seed: u64,
) -> ndarray::Array2<f64> {
// reproducible fast generator for f64s
let mut rng = Xoshiro256Plus::seed_from_u64(seed);
let data = (0..shape.0 * shape.1)
.map(|_| rng.gen())
.collect::<Vec<f64>>();
ndarray::Array2::from_shape_vec(shape, data).unwrap()
}

fn sparse_dense_dotprod_specialized(bench: &mut Bencher) {
let w = Array::range(0., 10., 0.00001);
let x = CsVec::new(1000000, vec![0, 200000, 800000], vec![1., 2., 3.]);
bench.iter(|| {
x.dot_dense(w.view());
});
fn generate_random_csr(shape: sprs::Shape, seed: u64) -> sprs::CsMat<f64> {
let mut rng = Xoshiro256Plus::seed_from_u64(seed);
let (rows, cols) = shape;
let nnz = rng.gen_range(1..rows * cols / 2);

let mut mat = sprs::TriMat::<f64>::new(shape);
for _ in 0..nnz {
let r = rng.gen_range(0..rows);
let c = rng.gen_range(0..cols);
let v = rng.gen::<f64>();
mat.add_triplet(r, c, v);
}

mat.to_csr()
}

fn sparse_dense_vec_matprod_default(bench: &mut Bencher) {
let w = Array::range(0., 10., 0.00001);
let a = CsMat::new(
(3, 1000000),
vec![0, 2, 4, 5],
vec![0, 1, 0, 2, 2],
vec![1., 2., 3., 4., 5.],
);
bench.iter(|| {
let _ = &a * &w;
});
// CSR-dense colmaj mulitplication
fn csr_dense_colmaj_mullacc(c: &mut Criterion) {
let mut group = c.benchmark_group("csr * dense (column major)");
group.sample_size(10);
group.measurement_time(std::time::Duration::from_secs(5));

// Testing on a finite element matrices
let mat = sprs::io::read_matrix_market::<f64, usize, _>(
"./data/matrix_market/bench/poisson4009.mtx",
)
.unwrap()
.to_csr::<usize>();

let shape = mat.shape();
let rhs = generate_random_array((shape.1, 200), 85);
let out = ndarray::Array2::<f64>::zeros((shape.0, 200));
run_benches(&mut group, &mat, &rhs, out, "FEM matrix");

// Testing on random generated matrices
const N_LOOP: usize = 10;
const MAX_LEFT_DIM: usize = 200;
const MAX_RIGHT_DIM: usize = 200;
const MAX_INNER_DIM: usize = 5000;

let mut rng = Xoshiro256Plus::seed_from_u64(150);

for _ in 0..N_LOOP {
let left_shape: sprs::Shape = (
rng.gen_range(10..=MAX_LEFT_DIM),
rng.gen_range(10..=MAX_INNER_DIM),
);
let right_shape: sprs::Shape =
(left_shape.1, rng.gen_range(1..=MAX_RIGHT_DIM));
let mat = generate_random_csr(left_shape, 24);
let rhs = generate_random_array(right_shape, 42);
let out = ndarray::Array2::<f64>::zeros((left_shape.0, right_shape.1));

let size = format!(
"{}x{} times {}x{}",
left_shape.0, left_shape.1, right_shape.0, right_shape.1
);

run_benches(&mut group, &mat, &rhs, out, &size);
}

group.finish();
}

fn sparse_dense_vec_matprod_specialized(bench: &mut Bencher) {
let w = Array::range(0., 10., 0.00001);
let a = CsMat::new(
(3, 1000000),
vec![0, 2, 4, 5],
vec![0, 1, 0, 2, 2],
vec![1., 2., 3., 4., 5.],
fn run_benches(
group: &mut BenchmarkGroup<WallTime>,
mat: &CsMat<f64>,
rhs: &Array2<f64>,
out: Array2<f64>,
label: &str,
) {
group.bench_with_input(
BenchmarkId::new("heap access", label),
&(mat, rhs, out.clone()),
|b, (mat, rhs, out)| {
b.iter(|| {
sprs::prod::csr_mulacc_dense_colmaj(
mat.view(),
rhs.view(),
out.clone().view_mut(),
)
})
},
);

group.bench_with_input(
BenchmarkId::new("cloned", label),
&(mat, rhs, out.clone()),
|b, (mat, rhs, out)| {
b.iter(|| {
sprs::prod::csr_mulacc_dense_colmaj_clone(
mat.view(),
rhs.view(),
out.clone().view_mut(),
)
})
},
);

group.bench_with_input(
BenchmarkId::new("copied", label),
&(mat, rhs, out.clone()),
|b, (mat, rhs, out)| {
b.iter(|| {
sprs::prod::csr_mulacc_dense_colmaj_copy(
mat.view(),
rhs.view(),
out.clone().view_mut(),
)
})
},
);

group.bench_with_input(
BenchmarkId::new("heap access no mul_add", label),
&(mat, rhs, out.clone()),
|b, (mat, rhs, out)| {
b.iter(|| {
sprs::prod::csr_dense_colmaj(
mat.view(),
rhs.view(),
out.clone().view_mut(),
)
})
},
);

group.bench_with_input(
BenchmarkId::new("cloned no mul_add", label),
&(mat, rhs, out.clone()),
|b, (mat, rhs, out)| {
b.iter(|| {
sprs::prod::csr_dense_colmaj_clone(
mat.view(),
rhs.view(),
out.clone().view_mut(),
)
})
},
);

group.bench_with_input(
BenchmarkId::new("copied no mul_add", label),
&(mat, rhs, out.clone()),
|b, (mat, rhs, out)| {
b.iter(|| {
sprs::prod::csr_dense_colmaj_copy(
mat.view(),
rhs.view(),
out.clone().view_mut(),
)
})
},
);
let rows = a.rows();
let cols = w.shape()[0];
let w_reshape = w.view().into_shape((1, cols)).unwrap();
let w_t = w_reshape.t();
let mut res = Array2::<f64>::zeros((rows, 1).f());
bench.iter(|| {
sprs::prod::csr_mulacc_dense_colmaj(
a.view(),
w_t.view(),
res.view_mut(),
);
});
}

benchmark_group!(
benches,
sparse_dense_dotprod_default,
sparse_dense_dotprod_specialized,
sparse_dense_vec_matprod_specialized,
sparse_dense_vec_matprod_default
);
benchmark_main!(benches);
criterion_group!(benches, csr_dense_colmaj_mullacc);
criterion_main!(benches);
Loading

0 comments on commit c1f0129

Please sign in to comment.