Skip to content

Commit

Permalink
perf: Add some simple benchmarks (#892)
Browse files Browse the repository at this point in the history
Adds some actual benchmarks, mainly extracted from the unit tests:

- Construct a complex `Type`
- Construct a `DFG` hugr
- Construct a `CFG` hugr

I intended to include these in a PR implementing this optimisation
suggestion
#891 (comment), but the
actual tests showed a consistent 4% slowdown on the hugr builders.
So I'd say it's important to have benchmarks :)
  • Loading branch information
aborgna-q committed Mar 25, 2024
1 parent f1e9600 commit d4569ef
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 6 deletions.
4 changes: 3 additions & 1 deletion quantinuum-hugr/benches/bench_main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
//! Benchmarks
#[allow(dead_code)]
#![allow(dead_code)]

mod benchmarks;

use criterion::criterion_main;

criterion_main! {
benchmarks::hugr::benches,
benchmarks::types::benches,
}
56 changes: 51 additions & 5 deletions quantinuum-hugr/benches/benchmarks/hugr.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,63 @@
#![allow(clippy::unit_arg)] // Required for black_box uses

use criterion::{criterion_group, AxisScale, Criterion, PlotConfiguration};
use criterion::{black_box, criterion_group, AxisScale, Criterion, PlotConfiguration};
use hugr::builder::{BuildError, CFGBuilder, DFGBuilder, Dataflow, DataflowHugr, HugrBuilder};
use hugr::extension::prelude::{BOOL_T, USIZE_T};
use hugr::extension::ExtensionSet;
use hugr::types::FunctionType;
use hugr::{type_row, Hugr};

fn bench_it_works(c: &mut Criterion) {
let mut group = c.benchmark_group("it_works");
pub fn simple_dfg_hugr() -> Hugr {
let dfg_builder =
DFGBuilder::new(FunctionType::new(type_row![BOOL_T], type_row![BOOL_T])).unwrap();
let [i1] = dfg_builder.input_wires_arr();
dfg_builder.finish_prelude_hugr_with_outputs([i1]).unwrap()
}

pub fn simple_cfg_builder<T: AsMut<Hugr> + AsRef<Hugr>>(
cfg_builder: &mut CFGBuilder<T>,
) -> Result<(), BuildError> {
let sum2_variants = vec![type_row![USIZE_T], type_row![USIZE_T]];
let mut entry_b =
cfg_builder.entry_builder(sum2_variants.clone(), type_row![], ExtensionSet::new())?;
let entry = {
let [inw] = entry_b.input_wires_arr();

let sum = entry_b.make_sum(1, sum2_variants, [inw])?;
entry_b.finish_with_outputs(sum, [])?
};
let mut middle_b = cfg_builder
.simple_block_builder(FunctionType::new(type_row![USIZE_T], type_row![USIZE_T]), 1)?;
let middle = {
let c = middle_b.add_load_const(hugr::ops::Const::unary_unit_sum());
let [inw] = middle_b.input_wires_arr();
middle_b.finish_with_outputs(c, [inw])?
};
let exit = cfg_builder.exit_block();
cfg_builder.branch(&entry, 0, &middle)?;
cfg_builder.branch(&middle, 0, &exit)?;
cfg_builder.branch(&entry, 1, &exit)?;
Ok(())
}

pub fn simple_cfg_hugr() -> Hugr {
let mut cfg_builder =
CFGBuilder::new(FunctionType::new(type_row![USIZE_T], type_row![USIZE_T])).unwrap();
simple_cfg_builder(&mut cfg_builder).unwrap();
cfg_builder.finish_prelude_hugr().unwrap()
}

fn bench_builder(c: &mut Criterion) {
let mut group = c.benchmark_group("builder");
group.plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic));
group.bench_function("it_works", |b| b.iter(|| 42));
group.bench_function("simple_dfg", |b| b.iter(|| black_box(simple_dfg_hugr())));
group.bench_function("simple_cfg", |b| b.iter(|| black_box(simple_cfg_hugr())));
group.finish();
}

criterion_group! {
name = benches;
config = Criterion::default();
targets =
bench_it_works,
bench_builder,
}
1 change: 1 addition & 0 deletions quantinuum-hugr/benches/benchmarks/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod hugr;
pub mod types;
36 changes: 36 additions & 0 deletions quantinuum-hugr/benches/benchmarks/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Required for black_box uses
#![allow(clippy::unit_arg)]
use hugr::extension::prelude::{QB_T, USIZE_T};
use hugr::ops::AliasDecl;
use hugr::types::{FunctionType, Type, TypeBound};

use criterion::{black_box, criterion_group, AxisScale, Criterion, PlotConfiguration};

/// Construct a complex type.
fn make_complex_type() -> Type {
let qb = QB_T;
let int = USIZE_T;
let q_register = Type::new_tuple(vec![qb; 8]);
let b_register = Type::new_tuple(vec![int; 8]);
let q_alias = Type::new_alias(AliasDecl::new("QReg", TypeBound::Any));
let sum = Type::new_sum([vec![q_register].into(), vec![q_alias].into()]);
Type::new_function(FunctionType::new(vec![sum], vec![b_register]))
}

fn bench_construction(c: &mut Criterion) {
let mut group = c.benchmark_group("types");
group.plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic));

group.bench_function("construction", |b| {
b.iter(|| black_box(make_complex_type()))
});

group.finish();
}

criterion_group! {
name = benches;
config = Criterion::default();
targets =
bench_construction,
}

0 comments on commit d4569ef

Please sign in to comment.