From b05559f6b4135dd11b671f33d8335f260845a046 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Fri, 24 Feb 2023 16:54:21 +0100 Subject: [PATCH 1/8] feat: Parallelize `commit` blinder poly generator method Solves the concerns raised in #151 related to the performance of the random poly generator inside of `commit`. Resolves: #151 --- halo2_proofs/src/plonk/vanishing/prover.rs | 29 +++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/halo2_proofs/src/plonk/vanishing/prover.rs b/halo2_proofs/src/plonk/vanishing/prover.rs index cc52273b59..dc18111cf4 100644 --- a/halo2_proofs/src/plonk/vanishing/prover.rs +++ b/halo2_proofs/src/plonk/vanishing/prover.rs @@ -1,8 +1,10 @@ use std::iter; -use ff::Field; +use ff::{Field, PrimeField}; use group::Curve; -use rand_core::RngCore; +use rand_chacha::ChaCha20Rng; +use rand_core::{RngCore, SeedableRng}; +use rayon::prelude::{IntoParallelRefIterator, ParallelIterator}; use super::Argument; use crate::{ @@ -47,10 +49,25 @@ impl Argument { transcript: &mut T, ) -> Result, Error> { // Sample a random polynomial of degree n - 1 - let mut random_poly = domain.empty_coeff(); - for coeff in random_poly.iter_mut() { - *coeff = C::Scalar::random(&mut rng); - } + let n_threads = std::thread::available_parallelism().unwrap().get(); + let needed_scalars = (1usize << domain.k() as usize) / n_threads; + + let thread_seeds: Vec = (0..needed_scalars) + .into_iter() + .map(|_| { + let mut seed = [0u8; 32]; + rng.fill_bytes(&mut seed); + ChaCha20Rng::from_seed(seed) + }) + .collect(); + + let rand_vec: Vec = thread_seeds + .par_iter() + .flat_map(|rng| vec![C::Scalar::random(rng.to_owned()); needed_scalars]) + .collect(); + + let random_poly: Polynomial = Polynomial::from_evals(rand_vec); + // Sample a random blinding factor let random_blind = Blind(C::Scalar::random(rng)); From 8c10e61ef0bfebb7b075fde02d91217d3d1e0f42 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Fri, 24 Feb 2023 17:12:45 +0100 Subject: [PATCH 2/8] chore: add `from_evals` for Polynomial --- halo2_proofs/src/poly.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/halo2_proofs/src/poly.rs b/halo2_proofs/src/poly.rs index 44cde43dd9..a837258dc8 100644 --- a/halo2_proofs/src/poly.rs +++ b/halo2_proofs/src/poly.rs @@ -145,6 +145,14 @@ impl Polynomial { pub fn num_coeffs(&self) -> usize { self.values.len() } + + /// Allows to create a Polynomial from a Vec. + pub fn from_evals(vector: Vec) -> Self { + Polynomial { + values: vector, + _marker: PhantomData, + } + } } impl Polynomial { From 1547fa174faf4709bd5a5cd8629b7ecbd6328ce2 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Fri, 24 Feb 2023 17:13:14 +0100 Subject: [PATCH 3/8] chore: add benches for commit_zk serial vs par --- halo2_proofs/Cargo.toml | 5 +++ halo2_proofs/benches/commit_zk.rs | 69 +++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 halo2_proofs/benches/commit_zk.rs diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index 38b001bce8..30992397db 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -27,6 +27,10 @@ rustdoc-args = ["--cfg", "docsrs", "--html-in-header", "katex-header.html"] name = "arithmetic" harness = false +[[bench]] +name = "commit_zk" +harness = false + [[bench]] name = "hashtocurve" harness = false @@ -53,6 +57,7 @@ rand_core = { version = "0.6", default-features = false } tracing = "0.1" blake2b_simd = "1" sha3 = "0.9.1" +rand_chacha = "0.3" # Developer tooling dependencies plotters = { version = "0.3.0", optional = true } diff --git a/halo2_proofs/benches/commit_zk.rs b/halo2_proofs/benches/commit_zk.rs new file mode 100644 index 0000000000..66d682e9fb --- /dev/null +++ b/halo2_proofs/benches/commit_zk.rs @@ -0,0 +1,69 @@ +#[macro_use] +extern crate criterion; + +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use group::ff::Field; +use halo2_proofs::poly::{LagrangeCoeff, Polynomial}; +use halo2_proofs::*; +use halo2curves::pasta::pallas::Scalar; +use rand_chacha::rand_core::RngCore; +use rand_chacha::ChaCha20Rng; +use rand_core::SeedableRng; +use rayon::{ + current_num_threads, + prelude::{IntoParallelRefIterator, ParallelIterator}, +}; + +fn rand_poly_serial(mut rng: ChaCha20Rng, domain: usize) -> Polynomial { + // Sample a random polynomial of degree n - 1 + let mut random_poly = vec![Scalar::zero(); 1 << domain]; + for coeff in random_poly.iter_mut() { + *coeff = Scalar::random(&mut rng); + } + assert_eq!(random_poly.len(), 1 << domain); + Polynomial::from_evals(random_poly) +} + +fn rand_poly_par(mut rng: ChaCha20Rng, domain: usize) -> Polynomial { + // Sample a random polynomial of degree n - 1 + let n_threads = current_num_threads(); + let needed_scalars = (1 << domain) / n_threads; + + let thread_seeds: Vec = (0..n_threads) + .into_iter() + .map(|_| { + let mut seed = [0u8; 32]; + rng.fill_bytes(&mut seed); + ChaCha20Rng::from_seed(seed) + }) + .collect(); + + let rand_vec: Vec = thread_seeds + .par_iter() + .flat_map(|rng| vec![Scalar::random(rng.to_owned()); needed_scalars]) + .collect(); + + assert_eq!(rand_vec.len(), 1 << domain); + Polynomial::from_evals(rand_vec) +} + +fn bench_commit(c: &mut Criterion) { + let mut group = c.benchmark_group("Blinder_poly"); + let rand = ChaCha20Rng::from_seed([1u8; 32]); + for i in [ + 18usize, 19usize, 20usize, 21usize, 22usize, 23usize, 24usize, 25usize, + ] + .iter() + { + group.bench_with_input(BenchmarkId::new("serial", i), i, |b, i| { + b.iter(|| rand_poly_serial(rand.clone(), *i)) + }); + group.bench_with_input(BenchmarkId::new("parallel", i), i, |b, i| { + b.iter(|| rand_poly_par(rand.clone(), *i)) + }); + } + group.finish(); +} + +criterion_group!(benches, bench_commit); +criterion_main!(benches); From 398dbcf7775de265b12f52585dac679633fe9fe1 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Fri, 24 Feb 2023 18:48:51 +0100 Subject: [PATCH 4/8] fix: Correct thread_seeds iter size --- halo2_proofs/src/plonk/vanishing/prover.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/halo2_proofs/src/plonk/vanishing/prover.rs b/halo2_proofs/src/plonk/vanishing/prover.rs index dc18111cf4..b29abd85c4 100644 --- a/halo2_proofs/src/plonk/vanishing/prover.rs +++ b/halo2_proofs/src/plonk/vanishing/prover.rs @@ -52,7 +52,7 @@ impl Argument { let n_threads = std::thread::available_parallelism().unwrap().get(); let needed_scalars = (1usize << domain.k() as usize) / n_threads; - let thread_seeds: Vec = (0..needed_scalars) + let thread_seeds: Vec = (0..n_threads) .into_iter() .map(|_| { let mut seed = [0u8; 32]; From 4402f45756dbde4fb6c7707cefd7f71119c74ed1 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Fri, 24 Feb 2023 18:54:06 +0100 Subject: [PATCH 5/8] fix: Clippy --- halo2_proofs/benches/commit_zk.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/halo2_proofs/benches/commit_zk.rs b/halo2_proofs/benches/commit_zk.rs index 66d682e9fb..e8a9173c5e 100644 --- a/halo2_proofs/benches/commit_zk.rs +++ b/halo2_proofs/benches/commit_zk.rs @@ -1,4 +1,3 @@ -#[macro_use] extern crate criterion; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; From 2a514ee9fedff8f7ccc9c679ed45631bef0f01fb Mon Sep 17 00:00:00 2001 From: CPerezz Date: Mon, 27 Feb 2023 10:37:42 +0100 Subject: [PATCH 6/8] chore: apply review suggestions --- halo2_proofs/src/plonk/vanishing/prover.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/halo2_proofs/src/plonk/vanishing/prover.rs b/halo2_proofs/src/plonk/vanishing/prover.rs index b29abd85c4..9e3593f5e9 100644 --- a/halo2_proofs/src/plonk/vanishing/prover.rs +++ b/halo2_proofs/src/plonk/vanishing/prover.rs @@ -4,7 +4,10 @@ use ff::{Field, PrimeField}; use group::Curve; use rand_chacha::ChaCha20Rng; use rand_core::{RngCore, SeedableRng}; -use rayon::prelude::{IntoParallelRefIterator, ParallelIterator}; +use rayon::{ + current_num_threads, + prelude::{IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator}, +}; use super::Argument; use crate::{ @@ -49,10 +52,10 @@ impl Argument { transcript: &mut T, ) -> Result, Error> { // Sample a random polynomial of degree n - 1 - let n_threads = std::thread::available_parallelism().unwrap().get(); + let n_threads = current_num_threads(); let needed_scalars = (1usize << domain.k() as usize) / n_threads; - let thread_seeds: Vec = (0..n_threads) + let mut thread_seeds: Vec = (0..n_threads) .into_iter() .map(|_| { let mut seed = [0u8; 32]; @@ -62,8 +65,13 @@ impl Argument { .collect(); let rand_vec: Vec = thread_seeds - .par_iter() - .flat_map(|rng| vec![C::Scalar::random(rng.to_owned()); needed_scalars]) + .par_iter_mut() + .flat_map(|mut rng| { + (0..needed_scalars) + .into_iter() + .map(|_| C::Scalar::random(&mut rng)) + .collect::>() + }) .collect(); let random_poly: Polynomial = Polynomial::from_evals(rand_vec); From 61bc9c8de1acd5d8369a586ce255a5a9d87af1cf Mon Sep 17 00:00:00 2001 From: CPerezz Date: Tue, 28 Feb 2023 08:44:43 +0100 Subject: [PATCH 7/8] fix: Inconsisten num of Scalars generated parallely This fix from @ed255 fixes an error on the code proposal which was rounding the num of Scalars to be generated and so, was producing failures. Co-authored-by: Edu --- halo2_proofs/benches/commit_zk.rs | 21 +++++++------- halo2_proofs/src/plonk/vanishing/prover.rs | 32 ++++++++++++---------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/halo2_proofs/benches/commit_zk.rs b/halo2_proofs/benches/commit_zk.rs index e8a9173c5e..e370c41c52 100644 --- a/halo2_proofs/benches/commit_zk.rs +++ b/halo2_proofs/benches/commit_zk.rs @@ -8,10 +8,7 @@ use halo2curves::pasta::pallas::Scalar; use rand_chacha::rand_core::RngCore; use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; -use rayon::{ - current_num_threads, - prelude::{IntoParallelRefIterator, ParallelIterator}, -}; +use rayon::{current_num_threads, prelude::*}; fn rand_poly_serial(mut rng: ChaCha20Rng, domain: usize) -> Polynomial { // Sample a random polynomial of degree n - 1 @@ -26,9 +23,12 @@ fn rand_poly_serial(mut rng: ChaCha20Rng, domain: usize) -> Polynomial Polynomial { // Sample a random polynomial of degree n - 1 let n_threads = current_num_threads(); - let needed_scalars = (1 << domain) / n_threads; + let n = 1usize << domain; + let n_chunks = n_threads + if n % n_threads != 0 { 1 } else { 0 }; + let mut rand_vec = vec![Scalar::zero(); n]; - let thread_seeds: Vec = (0..n_threads) + // We always round up the division by adding 1 extra seed. + let mut thread_seeds: Vec = (0..n_chunks) .into_iter() .map(|_| { let mut seed = [0u8; 32]; @@ -37,12 +37,11 @@ fn rand_poly_par(mut rng: ChaCha20Rng, domain: usize) -> Polynomial = thread_seeds - .par_iter() - .flat_map(|rng| vec![Scalar::random(rng.to_owned()); needed_scalars]) - .collect(); + thread_seeds + .par_iter_mut() + .zip_eq(rand_vec.par_chunks_mut(n / n_threads)) + .for_each(|(mut rng, chunk)| chunk.iter_mut().for_each(|v| *v = Scalar::random(&mut rng))); - assert_eq!(rand_vec.len(), 1 << domain); Polynomial::from_evals(rand_vec) } diff --git a/halo2_proofs/src/plonk/vanishing/prover.rs b/halo2_proofs/src/plonk/vanishing/prover.rs index 9e3593f5e9..9cfbfc6258 100644 --- a/halo2_proofs/src/plonk/vanishing/prover.rs +++ b/halo2_proofs/src/plonk/vanishing/prover.rs @@ -4,10 +4,7 @@ use ff::{Field, PrimeField}; use group::Curve; use rand_chacha::ChaCha20Rng; use rand_core::{RngCore, SeedableRng}; -use rayon::{ - current_num_threads, - prelude::{IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator}, -}; +use rayon::{current_num_threads, prelude::*}; use super::Argument; use crate::{ @@ -53,9 +50,12 @@ impl Argument { ) -> Result, Error> { // Sample a random polynomial of degree n - 1 let n_threads = current_num_threads(); - let needed_scalars = (1usize << domain.k() as usize) / n_threads; + let n = 1usize << domain.k() as usize; + let n_chunks = n_threads + if n % n_threads != 0 { 1 } else { 0 }; + let mut rand_vec = vec![C::Scalar::zero(); n]; - let mut thread_seeds: Vec = (0..n_threads) + // We always round up the division by adding 1 extra seed. + let mut thread_seeds: Vec = (0..n_chunks) .into_iter() .map(|_| { let mut seed = [0u8; 32]; @@ -64,17 +64,19 @@ impl Argument { }) .collect(); - let rand_vec: Vec = thread_seeds + thread_seeds .par_iter_mut() - .flat_map(|mut rng| { - (0..needed_scalars) - .into_iter() - .map(|_| C::Scalar::random(&mut rng)) - .collect::>() - }) - .collect(); + .zip_eq(rand_vec.par_chunks_mut(n / n_threads)) + .for_each(|(mut rng, chunk)| { + chunk + .iter_mut() + .for_each(|v| *v = C::Scalar::random(&mut rng)) + }); + + // Truncate the leftover elements of the Vec (if any). + rand_vec.truncate(1usize << domain.k() as usize); - let random_poly: Polynomial = Polynomial::from_evals(rand_vec); + let random_poly: Polynomial = domain.coeff_from_vec(rand_vec); // Sample a random blinding factor let random_blind = Blind(C::Scalar::random(rng)); From 0ff0396f5ed834eca4435ac9b4a7f2941556f782 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Tue, 28 Feb 2023 08:56:24 +0100 Subject: [PATCH 8/8] remove: legacy comments & code --- halo2_proofs/benches/commit_zk.rs | 12 +++++------- halo2_proofs/src/plonk/vanishing/prover.rs | 4 ---- halo2_proofs/src/poly.rs | 8 -------- 3 files changed, 5 insertions(+), 19 deletions(-) diff --git a/halo2_proofs/benches/commit_zk.rs b/halo2_proofs/benches/commit_zk.rs index e370c41c52..f1d2f70abf 100644 --- a/halo2_proofs/benches/commit_zk.rs +++ b/halo2_proofs/benches/commit_zk.rs @@ -2,7 +2,6 @@ extern crate criterion; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use group::ff::Field; -use halo2_proofs::poly::{LagrangeCoeff, Polynomial}; use halo2_proofs::*; use halo2curves::pasta::pallas::Scalar; use rand_chacha::rand_core::RngCore; @@ -10,24 +9,23 @@ use rand_chacha::ChaCha20Rng; use rand_core::SeedableRng; use rayon::{current_num_threads, prelude::*}; -fn rand_poly_serial(mut rng: ChaCha20Rng, domain: usize) -> Polynomial { +fn rand_poly_serial(mut rng: ChaCha20Rng, domain: usize) -> Vec { // Sample a random polynomial of degree n - 1 let mut random_poly = vec![Scalar::zero(); 1 << domain]; for coeff in random_poly.iter_mut() { *coeff = Scalar::random(&mut rng); } - assert_eq!(random_poly.len(), 1 << domain); - Polynomial::from_evals(random_poly) + + random_poly } -fn rand_poly_par(mut rng: ChaCha20Rng, domain: usize) -> Polynomial { +fn rand_poly_par(mut rng: ChaCha20Rng, domain: usize) -> Vec { // Sample a random polynomial of degree n - 1 let n_threads = current_num_threads(); let n = 1usize << domain; let n_chunks = n_threads + if n % n_threads != 0 { 1 } else { 0 }; let mut rand_vec = vec![Scalar::zero(); n]; - // We always round up the division by adding 1 extra seed. let mut thread_seeds: Vec = (0..n_chunks) .into_iter() .map(|_| { @@ -42,7 +40,7 @@ fn rand_poly_par(mut rng: ChaCha20Rng, domain: usize) -> Polynomial Argument { let n_chunks = n_threads + if n % n_threads != 0 { 1 } else { 0 }; let mut rand_vec = vec![C::Scalar::zero(); n]; - // We always round up the division by adding 1 extra seed. let mut thread_seeds: Vec = (0..n_chunks) .into_iter() .map(|_| { @@ -73,9 +72,6 @@ impl Argument { .for_each(|v| *v = C::Scalar::random(&mut rng)) }); - // Truncate the leftover elements of the Vec (if any). - rand_vec.truncate(1usize << domain.k() as usize); - let random_poly: Polynomial = domain.coeff_from_vec(rand_vec); // Sample a random blinding factor diff --git a/halo2_proofs/src/poly.rs b/halo2_proofs/src/poly.rs index a837258dc8..44cde43dd9 100644 --- a/halo2_proofs/src/poly.rs +++ b/halo2_proofs/src/poly.rs @@ -145,14 +145,6 @@ impl Polynomial { pub fn num_coeffs(&self) -> usize { self.values.len() } - - /// Allows to create a Polynomial from a Vec. - pub fn from_evals(vector: Vec) -> Self { - Polynomial { - values: vector, - _marker: PhantomData, - } - } } impl Polynomial {