diff --git a/math/Cargo.toml b/math/Cargo.toml index 9a6838a10..03d668fe4 100644 --- a/math/Cargo.toml +++ b/math/Cargo.toml @@ -39,6 +39,8 @@ const-random = "0.1.15" iai-callgrind.workspace = true proptest = "1.1.0" pprof = { version = "0.13.0", features = ["criterion", "flamegraph"] } +p3-baby-bear = { git = "https://github.com/Plonky3/Plonky3" } +p3-field = { git = "https://github.com/Plonky3/Plonky3" } [features] default = ["parallel", "std"] diff --git a/math/benches/criterion_field.rs b/math/benches/criterion_field.rs index 6e41cbb4b..e7733c1ad 100644 --- a/math/benches/criterion_field.rs +++ b/math/benches/criterion_field.rs @@ -5,13 +5,20 @@ mod fields; use fields::mersenne31::{mersenne31_extension_ops_benchmarks, mersenne31_ops_benchmarks}; use fields::mersenne31_montgomery::mersenne31_mont_ops_benchmarks; use fields::{ - stark252::starkfield_ops_benchmarks, u64_goldilocks::u64_goldilocks_ops_benchmarks, + babybear::{ + babybear_extension_ops_benchmarks, babybear_extension_ops_benchmarks_p3, + babybear_ops_benchmarks, babybear_p3_ops_benchmarks, + }, + stark252::starkfield_ops_benchmarks, + u64_goldilocks::u64_goldilocks_ops_benchmarks, u64_goldilocks_montgomery::u64_goldilocks_montgomery_ops_benchmarks, }; criterion_group!( name = field_benches; config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); - targets = mersenne31_ops_benchmarks, mersenne31_extension_ops_benchmarks, mersenne31_mont_ops_benchmarks, starkfield_ops_benchmarks, u64_goldilocks_ops_benchmarks, u64_goldilocks_montgomery_ops_benchmarks + targets = babybear_ops_benchmarks,babybear_extension_ops_benchmarks,babybear_p3_ops_benchmarks,babybear_extension_ops_benchmarks_p3, + mersenne31_extension_ops_benchmarks,mersenne31_ops_benchmarks,mersenne31_mont_ops_benchmarks,starkfield_ops_benchmarks,u64_goldilocks_ops_benchmarks + ,u64_goldilocks_montgomery_ops_benchmarks ); criterion_main!(field_benches); diff --git a/math/benches/fields/babybear.rs b/math/benches/fields/babybear.rs new file mode 100644 index 000000000..6a1bc250f --- /dev/null +++ b/math/benches/fields/babybear.rs @@ -0,0 +1,301 @@ +use criterion::Criterion; +use std::hint::black_box; + +use lambdaworks_math::field::fields::fft_friendly::quartic_babybear::Degree4BabyBearExtensionField; +use lambdaworks_math::field::{ + element::FieldElement, fields::fft_friendly::babybear::Babybear31PrimeField, +}; + +use p3_baby_bear::BabyBear; +use p3_field::extension::BinomialExtensionField; +use p3_field::{Field, FieldAlgebra}; + +use rand::random; +use rand::Rng; + +pub type F = FieldElement; +pub type Fp4E = FieldElement; +type EF4 = BinomialExtensionField; + +pub fn rand_field_elements(num: usize) -> Vec<(F, F)> { + let mut result = Vec::with_capacity(num); + for _ in 0..result.capacity() { + result.push((F::from(random::()), F::from(random::()))); + } + result +} + +pub fn rand_babybear_fp4_elements(num: usize) -> Vec<(Fp4E, Fp4E)> { + let mut result = Vec::with_capacity(num); + for _ in 0..num { + result.push(( + Fp4E::new([ + F::from(random::()), + F::from(random::()), + F::from(random::()), + F::from(random::()), + ]), + Fp4E::new([ + F::from(random::()), + F::from(random::()), + F::from(random::()), + F::from(random::()), + ]), + )); + } + result +} + +fn rand_babybear_elements_p3(num: usize) -> Vec<(BabyBear, BabyBear)> { + let mut rng = rand::thread_rng(); + (0..num) + .map(|_| (rng.gen::(), rng.gen::())) + .collect() +} + +fn rand_babybear_fp4_elements_p3(num: usize) -> Vec<(EF4, EF4)> { + let mut rng = rand::thread_rng(); + (0..num) + .map(|_| (rng.gen::(), rng.gen::())) + .collect() +} + +pub fn babybear_ops_benchmarks(c: &mut Criterion) { + let input: Vec> = [1, 10, 100, 1000, 10000, 100000, 1000000] + .into_iter() + .map(rand_field_elements) + .collect::>(); + let mut group = c.benchmark_group("BabyBear operations using Lambdaworks"); + + for i in input.clone().into_iter() { + group.bench_with_input(format!("Addition {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(x) + black_box(y)); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("Multiplication {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(x) * black_box(y)); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("Square {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, _) in i { + black_box(black_box(x).square()); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("Inverse {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, _) in i { + black_box(black_box(x).inv().unwrap()); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("Division {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(x) / black_box(y)); + } + }); + }); + } +} +pub fn babybear_extension_ops_benchmarks(c: &mut Criterion) { + let input: Vec> = [1, 10, 100, 1000, 10000, 100000, 1000000] + .into_iter() + .map(rand_babybear_fp4_elements) + .collect::>(); + + let mut group = c.benchmark_group("BabyBear Fp4 operations"); + + for i in input.clone().into_iter() { + group.bench_with_input(format!("Addition of Fp4 {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(x) + black_box(y)); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input( + format!("Multiplication of Fp4 {:?}", &i.len()), + &i, + |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(x) * black_box(y)); + } + }); + }, + ); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("Square of Fp4 {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, _) in i { + black_box(black_box(x).square()); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("Inverse of Fp4 {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(x) / black_box(y)); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("Division of Fp4 {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, _) in i { + black_box(black_box(x).inv().unwrap()); + } + }); + }); + } +} + +pub fn babybear_p3_ops_benchmarks(c: &mut Criterion) { + let input: Vec> = [1, 10, 100, 1000, 10000, 100000, 1000000] + .into_iter() + .map(rand_babybear_elements_p3) + .collect::>(); + + let mut group = c.benchmark_group("BabyBear operations using Plonky3"); + + for i in input.clone().into_iter() { + group.bench_with_input(format!("Addition {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(*x) + black_box(*y)); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("Multiplication {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(*x) * black_box(*y)); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("Square {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, _) in i { + black_box(black_box(x).square()); + } + }); + }); + } + for i in input.clone().into_iter() { + group.bench_with_input(format!("Inverse {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, _) in i { + black_box(black_box(x).inverse()); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("Division {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(*x) / black_box(*y)); + } + }); + }); + } +} + +pub fn babybear_extension_ops_benchmarks_p3(c: &mut Criterion) { + let input_sizes = [1, 10, 100, 1000, 10000, 100000, 1000000]; + let input: Vec> = input_sizes + .into_iter() + .map(rand_babybear_fp4_elements_p3) + .collect::>(); + + let mut group = c.benchmark_group("BabyBear Fp4 operations using Plonky3"); + + for i in input.clone().into_iter() { + group.bench_with_input(format!("Addition of Fp4 {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(*x) + black_box(*y)); + } + }); + }); + } + for i in input.clone().into_iter() { + group.bench_with_input( + format!("Multiplication of Fp4 {:?}", &i.len()), + &i, + |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(*x) * black_box(*y)); + } + }); + }, + ); + } + for i in input.clone().into_iter() { + group.bench_with_input(format!("Square of Fp4 {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, _) in i { + black_box(black_box(x).square()); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("Inverse of Fp4 {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, _) in i { + black_box(black_box(x).inverse()); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("Division of Fp4 {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(*x) / black_box(*y)); + } + }); + }); + } +} diff --git a/math/benches/fields/mod.rs b/math/benches/fields/mod.rs index a28773c6c..4de5940fa 100644 --- a/math/benches/fields/mod.rs +++ b/math/benches/fields/mod.rs @@ -1,3 +1,4 @@ +pub mod babybear; pub mod mersenne31; pub mod mersenne31_montgomery; pub mod stark252;