-
Notifications
You must be signed in to change notification settings - Fork 145
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into update-stark-docs
- Loading branch information
Showing
42 changed files
with
747 additions
and
706 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,102 +1,12 @@ | ||
use std::hint::black_box; | ||
|
||
use criterion::{criterion_group, criterion_main, Criterion}; | ||
use lambdaworks_math::{ | ||
field::fields::{ | ||
fft_friendly::stark_252_prime_field::{ | ||
MontgomeryConfigStark252PrimeField, Stark252PrimeField, | ||
}, | ||
montgomery_backed_prime_fields::IsModulus, | ||
}, | ||
unsigned_integer::{element::U256, montgomery::MontgomeryAlgorithms}, | ||
}; | ||
|
||
mod utils; | ||
use utils::u64_utils; | ||
|
||
pub fn starkfield_ops_benchmarks(c: &mut Criterion) { | ||
let mut group = c.benchmark_group("Stark FP operations"); | ||
let (x, y) = u64_utils::get_field_elements(); | ||
|
||
group.bench_with_input("add", &(x, y), |bench, (x, y)| { | ||
bench.iter(|| x + y); | ||
}); | ||
|
||
group.bench_with_input("mul", &(x, y), |bench, (x, y)| { | ||
bench.iter(|| x * y); | ||
}); | ||
|
||
group.bench_with_input("pow by 1", &x, |bench, x| { | ||
bench.iter(|| x.pow(1_u64)); | ||
}); | ||
|
||
// The non-boxed constants are intentional as they are | ||
// normally computed at compile time. | ||
group.bench_with_input("sos_square", &x, |bench, x| { | ||
bench.iter(|| { | ||
MontgomeryAlgorithms::sos_square( | ||
black_box(x.value()), | ||
&<MontgomeryConfigStark252PrimeField as IsModulus<U256>>::MODULUS, | ||
&Stark252PrimeField::MU, | ||
) | ||
}); | ||
}); | ||
|
||
group.bench_with_input("square", &x, |bench, x| { | ||
bench.iter(|| x.square()); | ||
}); | ||
|
||
group.bench_with_input("square with pow", &x, |bench, x| { | ||
bench.iter(|| x.pow(2_u64)); | ||
}); | ||
|
||
group.bench_with_input("square with mul", &x, |bench, x| { | ||
bench.iter(|| x * x); | ||
}); | ||
|
||
group.bench_with_input("pow", &(x, 5u64), |bench, (x, y)| { | ||
bench.iter(|| x.pow(*y)); | ||
}); | ||
|
||
group.bench_with_input("sub", &(x, y), |bench, (x, y)| { | ||
bench.iter(|| x - y); | ||
}); | ||
|
||
group.bench_with_input("inv", &x, |bench, x| { | ||
bench.iter(|| x.inv().unwrap()); | ||
}); | ||
|
||
group.bench_with_input("div", &(x, y), |bench, (x, y)| { | ||
bench.iter(|| x / y); | ||
}); | ||
|
||
group.bench_with_input("eq", &(x, y), |bench, (x, y)| { | ||
bench.iter(|| x == y); | ||
}); | ||
|
||
group.bench_with_input("sqrt", &x, |bench, x| { | ||
bench.iter(|| x.sqrt()); | ||
}); | ||
|
||
group.bench_with_input("sqrt squared", &(x * x), |bench, x| { | ||
bench.iter(|| x.sqrt()); | ||
}); | ||
|
||
// Unsigned integer bitwise operations | ||
let (x, y) = (x.value(), y.value()); | ||
|
||
group.bench_with_input("bitand", &(x, y), |bench, (&x, &y)| { | ||
bench.iter(|| x & y); | ||
}); | ||
|
||
group.bench_with_input("bitor", &(x, y), |bench, (&x, &y)| { | ||
bench.iter(|| x | y); | ||
}); | ||
use pprof::criterion::{Output, PProfProfiler}; | ||
|
||
group.bench_with_input("bitxor", &(x, y), |bench, (&x, &y)| { | ||
bench.iter(|| x ^ y); | ||
}); | ||
} | ||
mod fields; | ||
use fields::stark252::starkfield_ops_benchmarks; | ||
|
||
criterion_group!(starkfp, starkfield_ops_benchmarks); | ||
criterion_main!(starkfp); | ||
criterion_group!( | ||
name = field_benches; | ||
config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); | ||
targets = starkfield_ops_benchmarks | ||
); | ||
criterion_main!(field_benches); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod stark252; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
use std::hint::black_box; | ||
|
||
use criterion::Criterion; | ||
use lambdaworks_math::{ | ||
field::{ | ||
element::FieldElement, | ||
fields::{ | ||
fft_friendly::stark_252_prime_field::{ | ||
MontgomeryConfigStark252PrimeField, Stark252PrimeField, | ||
}, | ||
montgomery_backed_prime_fields::IsModulus, | ||
}, | ||
}, | ||
unsigned_integer::{ | ||
element::{UnsignedInteger, U256}, | ||
montgomery::MontgomeryAlgorithms, | ||
}, | ||
}; | ||
use rand::random; | ||
|
||
pub type F = FieldElement<Stark252PrimeField>; | ||
|
||
#[inline(never)] | ||
#[no_mangle] | ||
#[export_name = "util::rand_field_elements"] | ||
pub fn rand_field_elements(num: usize) -> Vec<(F, F)> { | ||
let mut result = Vec::with_capacity(num); | ||
for _ in 0..result.capacity() { | ||
let rand_a = UnsignedInteger { limbs: random() }; | ||
let rand_b = UnsignedInteger { limbs: random() }; | ||
result.push((F::new(rand_a), F::new(rand_b))); | ||
} | ||
result | ||
} | ||
|
||
pub fn starkfield_ops_benchmarks(c: &mut Criterion) { | ||
let input: Vec<Vec<(F, F)>> = [1, 10, 100, 1000, 10000, 100000, 1000000] | ||
.into_iter() | ||
.map(rand_field_elements) | ||
.collect::<Vec<_>>(); | ||
let mut group = c.benchmark_group("Stark FP operations"); | ||
|
||
for i in input.clone().into_iter() { | ||
group.bench_with_input(format!("add {:?}", &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!("mul {:?}", &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!("pow by 1 {:?}", &i.len()), &i, |bench, i| { | ||
bench.iter(|| { | ||
for (x, _) in i { | ||
black_box(black_box(x).pow(1_u64)); | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
// The non-boxed constants are intentional as they are | ||
// normally computed at compile time. | ||
for i in input.clone().into_iter() { | ||
group.bench_with_input(format!("sos_square {:?}", &i.len()), &i, |bench, i| { | ||
bench.iter(|| { | ||
for (x, _) in i { | ||
MontgomeryAlgorithms::sos_square( | ||
black_box(black_box(x.value())), | ||
&<MontgomeryConfigStark252PrimeField as IsModulus<U256>>::MODULUS, | ||
&Stark252PrimeField::MU, | ||
); | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
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!("square with pow {:?}", &i.len()), &i, |bench, i| { | ||
bench.iter(|| { | ||
for (x, _) in i { | ||
black_box(black_box(x).pow(2_u64)); | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
for i in input.clone().into_iter() { | ||
group.bench_with_input(format!("square with mul {:?}", &i.len()), &i, |bench, i| { | ||
bench.iter(|| { | ||
for (x, _) in i { | ||
black_box(black_box(x) * black_box(x)); | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
for i in input.clone().into_iter() { | ||
group.bench_with_input( | ||
format!("pow {:?}", &i.len()), | ||
&(i, 5u64), | ||
|bench, (i, a)| { | ||
bench.iter(|| { | ||
for (x, _) in i { | ||
black_box(black_box(x).pow(*a)); | ||
} | ||
}); | ||
}, | ||
); | ||
} | ||
|
||
for i in input.clone().into_iter() { | ||
group.bench_with_input(format!("sub {:?}", &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!("inv {:?}", &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!("div {:?}", &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!("eq {:?}", &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!("sqrt {:?}", &i.len()), &i, |bench, i| { | ||
bench.iter(|| { | ||
for (x, _) in i { | ||
black_box(black_box(x).sqrt()); | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
for i in input.clone().into_iter() { | ||
group.bench_with_input(format!("sqrt squared {:?}", &i.len()), &i, |bench, i| { | ||
let i: Vec<F> = i.iter().map(|(x, _)| x * x).collect(); | ||
bench.iter(|| { | ||
for x in &i { | ||
black_box(black_box(x).sqrt()); | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
for i in input.clone().into_iter() { | ||
group.bench_with_input(format!("bitand {:?}", &i.len()), &i, |bench, i| { | ||
// Note: we should strive to have the number of limbs be generic... ideally this benchmark group itself should have a generic type that we call into from the main runner. | ||
let i: Vec<(UnsignedInteger<4>, UnsignedInteger<4>)> = | ||
i.iter().map(|(x, y)| (*x.value(), *y.value())).collect(); | ||
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!("bitor {:?}", &i.len()), &i, |bench, i| { | ||
let i: Vec<(UnsignedInteger<4>, UnsignedInteger<4>)> = | ||
i.iter().map(|(x, y)| (*x.value(), *y.value())).collect(); | ||
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!("bitxor {:?}", &i.len()), &i, |bench, i| { | ||
let i: Vec<(UnsignedInteger<4>, UnsignedInteger<4>)> = | ||
i.iter().map(|(x, y)| (*x.value(), *y.value())).collect(); | ||
bench.iter(|| { | ||
for (x, y) in &i { | ||
black_box(black_box(*x) ^ black_box(*y)); | ||
} | ||
}); | ||
}); | ||
} | ||
} |
Oops, something went wrong.