From d4569efbdfb4188f8cf3adce0ed2d601a306b220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Borgna?= <121866228+aborgna-q@users.noreply.github.com> Date: Mon, 25 Mar 2024 15:51:58 +0000 Subject: [PATCH] perf: Add some simple benchmarks (#892) 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 https://github.com/CQCL/hugr/pull/891#issuecomment-2018046379, but the actual tests showed a consistent 4% slowdown on the hugr builders. So I'd say it's important to have benchmarks :) --- quantinuum-hugr/benches/bench_main.rs | 4 +- quantinuum-hugr/benches/benchmarks/hugr.rs | 56 +++++++++++++++++++-- quantinuum-hugr/benches/benchmarks/mod.rs | 1 + quantinuum-hugr/benches/benchmarks/types.rs | 36 +++++++++++++ 4 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 quantinuum-hugr/benches/benchmarks/types.rs diff --git a/quantinuum-hugr/benches/bench_main.rs b/quantinuum-hugr/benches/bench_main.rs index db6e5dc4e..bc0619c48 100644 --- a/quantinuum-hugr/benches/bench_main.rs +++ b/quantinuum-hugr/benches/bench_main.rs @@ -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, } diff --git a/quantinuum-hugr/benches/benchmarks/hugr.rs b/quantinuum-hugr/benches/benchmarks/hugr.rs index 231a1efa1..7da7b4c12 100644 --- a/quantinuum-hugr/benches/benchmarks/hugr.rs +++ b/quantinuum-hugr/benches/benchmarks/hugr.rs @@ -1,11 +1,57 @@ #![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 + AsRef>( + cfg_builder: &mut CFGBuilder, +) -> 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(); } @@ -13,5 +59,5 @@ criterion_group! { name = benches; config = Criterion::default(); targets = - bench_it_works, + bench_builder, } diff --git a/quantinuum-hugr/benches/benchmarks/mod.rs b/quantinuum-hugr/benches/benchmarks/mod.rs index 4b93580c2..a153caa15 100644 --- a/quantinuum-hugr/benches/benchmarks/mod.rs +++ b/quantinuum-hugr/benches/benchmarks/mod.rs @@ -1 +1,2 @@ pub mod hugr; +pub mod types; diff --git a/quantinuum-hugr/benches/benchmarks/types.rs b/quantinuum-hugr/benches/benchmarks/types.rs new file mode 100644 index 000000000..3b599983c --- /dev/null +++ b/quantinuum-hugr/benches/benchmarks/types.rs @@ -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, +}