Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update & clean benchmarks #165

Merged
merged 2 commits into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,11 @@ incremental = false
codegen-units = 1

[[bench]]
name = "less_than"
name = "field_arith"
harness = false

[[bench]]
name = "bn256_field"
harness = false

[[bench]]
name = "group"
davidnevadoc marked this conversation as resolved.
Show resolved Hide resolved
name = "curve"
harness = false

[[bench]]
Expand Down
51 changes: 0 additions & 51 deletions benches/bn256_field.rs

This file was deleted.

73 changes: 73 additions & 0 deletions benches/curve.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//! This benchmarks the basic EC operations.
//! It measures `G1` from the BN256 curve.
//!
//! To run this benchmark:
//!
//! cargo bench --bench curve

use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};
use ff::Field;
use group::prime::PrimeCurveAffine;
use halo2curves::bn256::G1;
use pasta_curves::arithmetic::CurveExt;
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;

fn bench_curve_ops<G: CurveExt>(c: &mut Criterion, name: &'static str) {
{
let mut rng = XorShiftRng::seed_from_u64(3141519u64);

// Generate 2 random points.
let mut p1 = G::random(&mut rng);
let p2 = G::random(&mut rng);
p1 += p2;

let p1_affine = G::AffineExt::from(p1);

let s = G::ScalarExt::random(&mut rng);

const N: usize = 1000;
let v: Vec<G> = (0..N).map(|_| p1 + G::random(&mut rng)).collect();

let mut q = vec![G::AffineExt::identity(); N];

let mut group = c.benchmark_group(format!("{} arithmetic", name));

group.significance_level(0.1).sample_size(1000);
group.throughput(Throughput::Elements(1));

group.bench_function(&format!("{name} check on curve"), move |b| {
b.iter(|| black_box(p1).is_on_curve())
});
group.bench_function(&format!("{name} check equality"), move |b| {
b.iter(|| black_box(p1) == black_box(p1))
});
group.bench_function(&format!("{name} to affine"), move |b| {
b.iter(|| G::AffineExt::from(black_box(p1)))
});
group.bench_function(&format!("{name} doubling"), move |b| {
b.iter(|| black_box(p1).double())
});
group.bench_function(&format!("{name} addition"), move |b| {
b.iter(|| black_box(p1).add(&p2))
});
group.bench_function(&format!("{name} mixed addition"), move |b| {
b.iter(|| black_box(p2).add(&p1_affine))
});
group.bench_function(&format!("{name} scalar multiplication"), move |b| {
b.iter(|| black_box(p1) * black_box(s))
});
group.bench_function(&format!("{name} batch to affine n={N}"), move |b| {
b.iter(|| {
G::batch_normalize(black_box(&v), black_box(&mut q));
})
});
}
}

fn bench_bn256_ops(c: &mut Criterion) {
bench_curve_ops::<G1>(c, "BN256")
}

criterion_group!(benches, bench_bn256_ops);
criterion_main!(benches);
17 changes: 11 additions & 6 deletions benches/fft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//!
//! To run this benchmark:
//!
//! cargo bench -- fft
//! cargo bench --bench fft
//!
//! Caveat: The multicore benchmark assumes:
//! 1. a multi-core system
Expand All @@ -17,17 +17,21 @@ use criterion::{BenchmarkId, Criterion};
use group::ff::Field;
use halo2curves::bn256::Fr as Scalar;
use halo2curves::fft::best_fft;
use rand_core::OsRng;
use rand::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;
use std::ops::Range;
use std::time::SystemTime;

const RANGE: Range<u32> = 3..19;
const SEED: [u8; 16] = [
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 0xe5,
];

fn generate_data(k: u32) -> Vec<Scalar> {
fn generate_data(k: u32, mut rng: impl RngCore) -> Vec<Scalar> {
let n = 1 << k;
let timer = SystemTime::now();
println!("\n\nGenerating 2^{k} = {n} values..",);
let data: Vec<Scalar> = (0..n).map(|_| Scalar::random(OsRng)).collect();
let data: Vec<Scalar> = (0..n).map(|_| Scalar::random(&mut rng)).collect();
let end = timer.elapsed().unwrap();
println!(
"Generating 2^{k} = {n} values took: {} sec.\n\n",
Expand All @@ -38,8 +42,9 @@ fn generate_data(k: u32) -> Vec<Scalar> {

fn fft(c: &mut Criterion) {
Copy link
Member

@adria0 adria0 Jun 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIS best_fft can use different algorithms, depending on log_n <= log_threads.
Asking myself if it's a good performance test if we do not control the number of threads here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm 🤔 I'd say it only makes sense to compare results when the number of threads used is the same (and therefore the same algorithm is used). It is true that this can show up as a weird trend when comparing the performance of the fft at different sizes in the same system.

let max_k = RANGE.max().unwrap_or(16);
let mut data = generate_data(max_k);
let omega = Scalar::random(OsRng);
let mut rng = XorShiftRng::from_seed(SEED);
let mut data = generate_data(max_k, &mut rng);
let omega = Scalar::random(&mut rng);
let mut group = c.benchmark_group("fft");
for k in RANGE {
group.bench_function(BenchmarkId::new("k", k), |b| {
Expand Down
70 changes: 70 additions & 0 deletions benches/field_arith.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//! This benchmarks the basic FF operations.
//! It measures the base field `Fq` and scalar field `Fr` from the BN256 curve.
//!
//! To run this benchmark:
//!
//! cargo bench --bench field_arith

use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};
use halo2curves::{
bn256::{Fq, Fr},
ff::Field,
ff_ext::Legendre,
};
use rand::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;

const SEED: [u8; 16] = [
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 0xe5,
];
fn bench_field_arithmetic<F: Field + Legendre>(c: &mut Criterion, name: &'static str) {
let mut rng = XorShiftRng::from_seed(SEED);

let a = <F as Field>::random(&mut rng);
let b = <F as Field>::random(&mut rng);
let exp = rng.next_u64();

let mut group = c.benchmark_group(format!("{} arithmetic", name));

group.significance_level(0.1).sample_size(1000);
group.throughput(Throughput::Elements(1));

group.bench_function(format!("{}_add", name), |bencher| {
bencher.iter(|| black_box(&a).add(black_box(&b)))
});
group.bench_function(format!("{}_double", name), |bencher| {
bencher.iter(|| black_box(&a).double())
});
group.bench_function(format!("{}_sub", name), |bencher| {
bencher.iter(|| black_box(&a).sub(black_box(&b)))
});
group.bench_function(format!("{}_neg", name), |bencher| {
bencher.iter(|| black_box(&a).neg())
});
group.bench_function(format!("{}_mul", name), |bencher| {
bencher.iter(|| black_box(&a).mul(black_box(&b)))
});
group.bench_function(format!("{}_square", name), |bencher| {
bencher.iter(|| black_box(&a).square())
});
group.bench_function(format!("{}_pow_vartime", name), |bencher| {
bencher.iter(|| black_box(&a).pow_vartime(black_box(&[exp])))
});
group.bench_function(format!("{}_invert", name), |bencher| {
bencher.iter(|| black_box(&a).invert())
});
group.bench_function(format!("{}_legendre", name), |bencher| {
bencher.iter(|| black_box(&a).legendre())
});
group.finish()
davidnevadoc marked this conversation as resolved.
Show resolved Hide resolved
}

fn bench_bn256_base_field(c: &mut Criterion) {
bench_field_arithmetic::<Fq>(c, "Fq")
}
fn bench_bn256_scalar_field(c: &mut Criterion) {
bench_field_arithmetic::<Fr>(c, "Fr")
}

criterion_group!(benches, bench_bn256_base_field, bench_bn256_scalar_field);
criterion_main!(benches);
52 changes: 0 additions & 52 deletions benches/group.rs

This file was deleted.

60 changes: 20 additions & 40 deletions benches/hash_to_curve.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,25 @@
//! This benchmarks basic the hash-to-curve algorithm.
//! It measures `G1` from the BN256 curve.
//!
//! To run this benchmark:
//!
//! cargo bench --bench hash_to_curve

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use halo2curves::bn256::G1;
use pasta_curves::arithmetic::CurveExt;
use rand_core::{OsRng, RngCore};
use rand::SeedableRng;
use rand_core::RngCore;
use rand_xorshift::XorShiftRng;
use std::iter;

fn hash_to_secp256k1(c: &mut Criterion) {
hash_to_curve::<halo2curves::secp256k1::Secp256k1>(c, "Secp256k1");
}

fn hash_to_secq256k1(c: &mut Criterion) {
hash_to_curve::<halo2curves::secq256k1::Secq256k1>(c, "Secq256k1");
}

fn hash_to_secp256r1(c: &mut Criterion) {
hash_to_curve::<halo2curves::secp256r1::Secp256r1>(c, "Secp256r1");
}

fn hash_to_pallas(c: &mut Criterion) {
hash_to_curve::<halo2curves::pasta::Ep>(c, "Pallas");
}

fn hash_to_vesta(c: &mut Criterion) {
hash_to_curve::<halo2curves::pasta::Eq>(c, "Vesta");
}

fn hash_to_bn256(c: &mut Criterion) {
hash_to_curve::<halo2curves::bn256::G1>(c, "Bn256");
}

fn hash_to_grumpkin(c: &mut Criterion) {
hash_to_curve::<halo2curves::grumpkin::G1>(c, "Grumpkin");
}

const SEED: [u8; 16] = [
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 0xe5,
];
fn hash_to_curve<G: CurveExt>(c: &mut Criterion, name: &'static str) {
{
let hasher = G::hash_to_curve("test");
let mut rng = OsRng;
let mut rng = XorShiftRng::from_seed(SEED);
let message = iter::repeat_with(|| rng.next_u32().to_be_bytes())
.take(1024)
.flatten()
Expand All @@ -46,14 +31,9 @@ fn hash_to_curve<G: CurveExt>(c: &mut Criterion, name: &'static str) {
}
}

criterion_group!(
benches,
hash_to_secp256k1,
hash_to_secq256k1,
hash_to_secp256r1,
hash_to_pallas,
hash_to_vesta,
hash_to_bn256,
hash_to_grumpkin,
);
fn hash_to_bn256(c: &mut Criterion) {
hash_to_curve::<G1>(c, "BN256");
}

criterion_group!(benches, hash_to_bn256,);
davidnevadoc marked this conversation as resolved.
Show resolved Hide resolved
criterion_main!(benches);
Loading