Merge pull request #105 from EspressoSystems/arcpariter-new Parallelization optimizations
jump to
@@ -4,7 +4,7 @@ use ark_poly::MultilinearExtension;
use ark_std::{end_timer, rand::RngCore, start_timer}; #[cfg(feature = "parallel")] use rayon::prelude::{IndexedParallelIterator, IntoParallelRefMutIterator, ParallelIterator}; -use std::rc::Rc; +use std::sync::Arc; pub use ark_poly::DenseMultilinearExtension;@@ -16,7 +16,7 @@ pub fn random_mle_list<F: PrimeField, R: RngCore>(
nv: usize, degree: usize, rng: &mut R, -) -> (Vec<Rc<DenseMultilinearExtension<F>>>, F) { +) -> (Vec<Arc<DenseMultilinearExtension<F>>>, F) { let start = start_timer!(|| "sample random mle list"); let mut multiplicands = Vec::with_capacity(degree); for _ in 0..degree {@@ -37,7 +37,7 @@ }
let list = multiplicands .into_iter() - .map(|x| Rc::new(DenseMultilinearExtension::from_evaluations_vec(nv, x))) + .map(|x| Arc::new(DenseMultilinearExtension::from_evaluations_vec(nv, x))) .collect(); end_timer!(start);@@ -49,7 +49,7 @@ pub fn random_zero_mle_list<F: PrimeField, R: RngCore>(
nv: usize, degree: usize, rng: &mut R, -) -> Vec<Rc<DenseMultilinearExtension<F>>> { +) -> Vec<Arc<DenseMultilinearExtension<F>>> { let start = start_timer!(|| "sample random zero mle list"); let mut multiplicands = Vec::with_capacity(degree);@@ -65,7 +65,7 @@ }
let list = multiplicands .into_iter() - .map(|x| Rc::new(DenseMultilinearExtension::from_evaluations_vec(nv, x))) + .map(|x| Arc::new(DenseMultilinearExtension::from_evaluations_vec(nv, x))) .collect(); end_timer!(start);@@ -81,12 +81,12 @@ /// A list of MLEs that represents an identity permutation
pub fn identity_permutation_mles<F: PrimeField>( num_vars: usize, num_chunks: usize, -) -> Vec<Rc<DenseMultilinearExtension<F>>> { +) -> Vec<Arc<DenseMultilinearExtension<F>>> { let mut res = vec![]; for i in 0..num_chunks { let shift = (i * (1 << num_vars)) as u64; let s_id_vec = (shift..shift + (1u64 << num_vars)).map(F::from).collect(); - res.push(Rc::new(DenseMultilinearExtension::from_evaluations_vec( + res.push(Arc::new(DenseMultilinearExtension::from_evaluations_vec( num_vars, s_id_vec, ))); }@@ -113,12 +113,12 @@ pub fn random_permutation_mles<F: PrimeField, R: RngCore>(
num_vars: usize, num_chunks: usize, rng: &mut R, -) -> Vec<Rc<DenseMultilinearExtension<F>>> { +) -> Vec<Arc<DenseMultilinearExtension<F>>> { let s_perm_vec = random_permutation(num_vars, num_chunks, rng); let mut res = vec![]; let n = 1 << num_vars; for i in 0..num_chunks { - res.push(Rc::new(DenseMultilinearExtension::from_evaluations_vec( + res.push(Arc::new(DenseMultilinearExtension::from_evaluations_vec( num_vars, s_perm_vec[i * n..i * n + n].to_vec(), )));@@ -160,16 +160,9 @@ res[i] = data[i] + (data[(i << 1) + 1] - data[i << 1]) * point;
} #[cfg(feature = "parallel")] - if nv >= 13 { - // on my computer we parallelization doesn't help till nv >= 13 - res.par_iter_mut().enumerate().for_each(|(i, x)| { - *x = data[i << 1] + (data[(i << 1) + 1] - data[i << 1]) * point; - }); - } else { - for i in 0..(1 << (nv - 1)) { - res[i] = data[i << 1] + (data[(i << 1) + 1] - data[i << 1]) * point; - } - } + res.par_iter_mut().enumerate().for_each(|(i, x)| { + *x = data[i << 1] + (data[(i << 1) + 1] - data[i << 1]) * point; + }); res }@@ -203,8 +196,8 @@
/// merge a set of polynomials. Returns an error if the /// polynomials do not share a same number of nvs. pub fn merge_polynomials<F: PrimeField>( - polynomials: &[Rc<DenseMultilinearExtension<F>>], -) -> Result<Rc<DenseMultilinearExtension<F>>, ArithErrors> { + polynomials: &[Arc<DenseMultilinearExtension<F>>], +) -> Result<Arc<DenseMultilinearExtension<F>>, ArithErrors> { let nv = polynomials[0].num_vars(); for poly in polynomials.iter() { if nv != poly.num_vars() {@@ -220,7 +213,7 @@ for poly in polynomials.iter() {
scalars.extend_from_slice(poly.to_evaluations().as_slice()); } scalars.extend_from_slice(vec![F::zero(); (1 << merged_nv) - scalars.len()].as_ref()); - Ok(Rc::new(DenseMultilinearExtension::from_evaluations_vec( + Ok(Arc::new(DenseMultilinearExtension::from_evaluations_vec( merged_nv, scalars, ))) }@@ -279,16 +272,9 @@ res[b] = data[b] + (data[b + half_len] - data[b]) * point;
} #[cfg(feature = "parallel")] - if nv >= 13 { - // on my computer we parallelization doesn't help till nv >= 13 - res.par_iter_mut().enumerate().for_each(|(i, x)| { - *x = data[i] + (data[i + half_len] - data[i]) * point; - }); - } else { - for b in 0..(1 << (nv - 1)) { - res[b] = data[b] + (data[b + half_len] - data[b]) * point; - } - } + res.par_iter_mut().enumerate().for_each(|(i, x)| { + *x = data[i] + (data[i + half_len] - data[i]) * point; + }); res }
@@ -11,7 +11,7 @@ rand::{Rng, RngCore},
start_timer, }; use rayon::prelude::*; -use std::{cmp::max, collections::HashMap, marker::PhantomData, ops::Add, rc::Rc}; +use std::{cmp::max, collections::HashMap, marker::PhantomData, ops::Add, sync::Arc}; #[rustfmt::skip] /// A virtual polynomial is a sum of products of multilinear polynomials;@@ -48,7 +48,7 @@ /// list of reference to products (as usize) of multilinear extension
pub products: Vec<(F, Vec<usize>)>, /// Stores multilinear extensions in which product multiplicand can refer /// to. - pub flattened_ml_extensions: Vec<Rc<DenseMultilinearExtension<F>>>, + pub flattened_ml_extensions: Vec<Arc<DenseMultilinearExtension<F>>>, /// Pointers to the above poly extensions raw_pointers_lookup_table: HashMap<*const DenseMultilinearExtension<F>, usize>, }@@ -71,7 +71,7 @@ fn add(self, other: &VirtualPolynomial<F>) -> Self::Output {
let start = start_timer!(|| "virtual poly add"); let mut res = self.clone(); for products in other.products.iter() { - let cur: Vec<Rc<DenseMultilinearExtension<F>>> = products + let cur: Vec<Arc<DenseMultilinearExtension<F>>> = products .1 .iter() .map(|&x| other.flattened_ml_extensions[x].clone())@@ -102,8 +102,8 @@ }
} /// Creates an new virtual polynomial from a MLE and its coefficient. - pub fn new_from_mle(mle: &Rc<DenseMultilinearExtension<F>>, coefficient: F) -> Self { - let mle_ptr: *const DenseMultilinearExtension<F> = Rc::as_ptr(mle); + pub fn new_from_mle(mle: &Arc<DenseMultilinearExtension<F>>, coefficient: F) -> Self { + let mle_ptr: *const DenseMultilinearExtension<F> = Arc::as_ptr(mle); let mut hm = HashMap::new(); hm.insert(mle_ptr, 0);@@ -129,10 +129,10 @@ /// The MLEs will be multiplied together, and then multiplied by the scalar
/// `coefficient`. pub fn add_mle_list( &mut self, - mle_list: impl IntoIterator<Item = Rc<DenseMultilinearExtension<F>>>, + mle_list: impl IntoIterator<Item = Arc<DenseMultilinearExtension<F>>>, coefficient: F, ) -> Result<(), ArithErrors> { - let mle_list: Vec<Rc<DenseMultilinearExtension<F>>> = mle_list.into_iter().collect(); + let mle_list: Vec<Arc<DenseMultilinearExtension<F>>> = mle_list.into_iter().collect(); let mut indexed_product = Vec::with_capacity(mle_list.len()); if mle_list.is_empty() {@@ -151,7 +151,7 @@ mle.num_vars, self.aux_info.num_variables
))); } - let mle_ptr: *const DenseMultilinearExtension<F> = Rc::as_ptr(&mle); + let mle_ptr: *const DenseMultilinearExtension<F> = Arc::as_ptr(&mle); if let Some(index) = self.raw_pointers_lookup_table.get(&mle_ptr) { indexed_product.push(*index) } else {@@ -171,7 +171,7 @@ /// - multiple each product by MLE and its coefficient.
/// Returns an error if the MLE has a different `num_vars` from self. pub fn mul_by_mle( &mut self, - mle: Rc<DenseMultilinearExtension<F>>, + mle: Arc<DenseMultilinearExtension<F>>, coefficient: F, ) -> Result<(), ArithErrors> { let start = start_timer!(|| "mul by mle");@@ -183,7 +183,7 @@ mle.num_vars, self.aux_info.num_variables
))); } - let mle_ptr: *const DenseMultilinearExtension<F> = Rc::as_ptr(&mle); + let mle_ptr: *const DenseMultilinearExtension<F> = Arc::as_ptr(&mle); // check if this mle already exists in the virtual polynomial let mle_index = match self.raw_pointers_lookup_table.get(&mle_ptr) {@@ -350,11 +350,11 @@ /// over r, which is
/// eq(x,y) = \prod_i=1^num_var (x_i * r_i + (1-x_i)*(1-r_i)) pub fn build_eq_x_r<F: PrimeField>( r: &[F], -) -> Result<Rc<DenseMultilinearExtension<F>>, ArithErrors> { +) -> Result<Arc<DenseMultilinearExtension<F>>, ArithErrors> { let evals = build_eq_x_r_vec(r)?; let mle = DenseMultilinearExtension::from_evaluations_vec(r.len(), evals); - Ok(Rc::new(mle)) + Ok(Arc::new(mle)) } /// This function build the eq(x, r) polynomial for any given r, and output the /// evaluation of eq(x, r) in its vector form.@@ -364,8 +364,6 @@ /// eq(x,y) = \prod_i=1^num_var (x_i * y_i + (1-x_i)*(1-y_i))
/// over r, which is /// eq(x,y) = \prod_i=1^num_var (x_i * r_i + (1-x_i)*(1-r_i)) pub fn build_eq_x_r_vec<F: PrimeField>(r: &[F]) -> Result<Vec<F>, ArithErrors> { - let start = start_timer!(|| format!("build eq_x_r of size {}", r.len())); - // we build eq(x,r) from its evaluations // we want to evaluate eq(x,r) over x \in {0, 1}^num_vars // for example, with num_vars = 4, x is a binary vector of 4, then@@ -380,7 +378,6 @@
let mut eval = Vec::new(); build_eq_x_r_helper(r, &mut eval)?; - end_timer!(start); Ok(eval) }@@ -511,9 +508,7 @@ // Evaluate
// eq(x,y) = \prod_i=1^num_var (x_i * y_i + (1-x_i)*(1-y_i)) // over r, which is // eq(x,y) = \prod_i=1^num_var (x_i * r_i + (1-x_i)*(1-r_i)) - fn build_eq_x_r_for_test<F: PrimeField>(r: &[F]) -> Rc<DenseMultilinearExtension<F>> { - let start = start_timer!(|| "zero check naive build eq_x_r"); - + fn build_eq_x_r_for_test<F: PrimeField>(r: &[F]) -> Arc<DenseMultilinearExtension<F>> { // we build eq(x,r) from its evaluations // we want to evaluate eq(x,r) over x \in {0, 1}^num_vars // for example, with num_vars = 4, x is a binary vector of 4, then@@ -545,8 +540,7 @@ }
let mle = DenseMultilinearExtension::from_evaluations_vec(num_var, eval); - let res = Rc::new(mle); - end_timer!(start); + let res = Arc::new(mle); res } }
@@ -238,8 +238,8 @@ let pcs_srs =
MultilinearKzgPCS::<Bls12_381>::gen_srs_for_testing(&mut rng, SUPPORTED_SIZE)?; let nv = MAX_NUM_VARS; - let vanilla_gate = CustomizedGates::vanilla_plonk_gate(); - test_mock_circuit_zkp_helper(nv, &vanilla_gate, &pcs_srs)?; + let turboplonk_gate = CustomizedGates::jellyfish_turbo_plonk_gate(); + test_mock_circuit_zkp_helper(nv, &turboplonk_gate, &pcs_srs)?; Ok(()) }
@@ -2,7 +2,7 @@ use crate::{build_mle, errors::HyperPlonkErrors};
use ark_ff::PrimeField; use ark_poly::DenseMultilinearExtension; use ark_std::log2; -use std::rc::Rc; +use std::sync::Arc; /// A row of selector of width `#selectors` #[derive(Debug, Clone, PartialEq, Eq)]@@ -67,7 +67,7 @@ ///
/// output mle(a1,b1,c1, ...), mle(a2,b2,c2, ...), ... pub fn build_mles( matrix: &[Self], - ) -> Result<Vec<Rc<DenseMultilinearExtension<F>>>, HyperPlonkErrors> { + ) -> Result<Vec<Arc<DenseMultilinearExtension<F>>>, HyperPlonkErrors> { build_mle!(matrix) } }
@@ -9,7 +9,10 @@ use arithmetic::{evaluate_opt, gen_eval_point, VPAuxInfo};
use ark_ec::PairingEngine; use ark_poly::DenseMultilinearExtension; use ark_std::{end_timer, log2, start_timer, One, Zero}; -use std::{marker::PhantomData, rc::Rc}; +use rayon::iter::IntoParallelRefIterator; +#[cfg(feature = "parallel")] +use rayon::iter::ParallelIterator; +use std::{marker::PhantomData, sync::Arc}; use subroutines::{ pcs::prelude::{Commitment, PolynomialCommitmentScheme}, poly_iop::{@@ -28,7 +31,7 @@ // But since PCS::Polynomial can be both univariate or multivariate in our implementation
// we cannot bound PCS::Polynomial with a property trait bound. PCS: PolynomialCommitmentScheme< E, - Polynomial = Rc<DenseMultilinearExtension<E::Fr>>, + Polynomial = Arc<DenseMultilinearExtension<E::Fr>>, Point = Vec<E::Fr>, Evaluation = E::Fr, Commitment = Commitment<E>,@@ -56,7 +59,7 @@ let mut permutation_oracles = vec![];
let mut perm_comms = vec![]; let chunk_size = 1 << num_vars; for i in 0..index.num_witness_columns() { - let perm_oracle = Rc::new(DenseMultilinearExtension::from_evaluations_slice( + let perm_oracle = Arc::new(DenseMultilinearExtension::from_evaluations_slice( num_vars, &index.permutation[i * chunk_size..(i + 1) * chunk_size], ));@@ -66,14 +69,14 @@ perm_comms.push(perm_comm);
} // build selector oracles and commit to it - let selector_oracles: Vec<Rc<DenseMultilinearExtension<E::Fr>>> = index + let selector_oracles: Vec<Arc<DenseMultilinearExtension<E::Fr>>> = index .selectors .iter() - .map(|s| Rc::new(DenseMultilinearExtension::from(s))) + .map(|s| Arc::new(DenseMultilinearExtension::from(s))) .collect(); let selector_commitments = selector_oracles - .iter() + .par_iter() .map(|poly| PCS::commit(&pcs_prover_param, poly)) .collect::<Result<Vec<_>, _>>()?;@@ -168,13 +171,13 @@ // transcript
// ======================================================================= let step = start_timer!(|| "commit witnesses"); - let witness_polys: Vec<Rc<DenseMultilinearExtension<E::Fr>>> = witnesses + let witness_polys: Vec<Arc<DenseMultilinearExtension<E::Fr>>> = witnesses .iter() - .map(|w| Rc::new(DenseMultilinearExtension::from(w))) + .map(|w| Arc::new(DenseMultilinearExtension::from(w))) .collect(); let witness_commits = witness_polys - .iter() + .par_iter() .map(|x| PCS::commit(&pk.pcs_param, x).unwrap()) .collect::<Vec<_>>(); for w_com in witness_commits.iter() {@@ -663,15 +666,15 @@ // w1 := [0, 1, 2, 3]
let w1 = WitnessColumn(vec![ E::Fr::zero(), E::Fr::one(), - E::Fr::from(2u64), - E::Fr::from(3u64), + E::Fr::from(2u128), + E::Fr::from(3u128), ]); // w2 := [0^5, 1^5, 2^5, 3^5] let w2 = WitnessColumn(vec![ E::Fr::zero(), E::Fr::one(), - E::Fr::from(32u64), - E::Fr::from(243u64), + E::Fr::from(32u128), + E::Fr::from(243u128), ]); // public input = w1 let pi = w1.clone();
@@ -5,7 +5,7 @@ use ark_ec::PairingEngine;
use ark_ff::PrimeField; use ark_poly::DenseMultilinearExtension; use ark_std::log2; -use std::rc::Rc; +use std::sync::Arc; use subroutines::{ pcs::PolynomialCommitmentScheme, poly_iop::prelude::{PermutationCheck, ZeroCheck},@@ -126,9 +126,9 @@ pub struct HyperPlonkProvingKey<E: PairingEngine, PCS: PolynomialCommitmentScheme<E>> {
/// Hyperplonk instance parameters pub params: HyperPlonkParams, /// The preprocessed permutation polynomials - pub permutation_oracles: Vec<Rc<DenseMultilinearExtension<E::Fr>>>, + pub permutation_oracles: Vec<Arc<DenseMultilinearExtension<E::Fr>>>, /// The preprocessed selector polynomials - pub selector_oracles: Vec<Rc<DenseMultilinearExtension<E::Fr>>>, + pub selector_oracles: Vec<Arc<DenseMultilinearExtension<E::Fr>>>, /// Commitments to the preprocessed selector polynomials pub selector_commitments: Vec<PCS::Commitment>, /// Commitments to the preprocessed permutation polynomials
@@ -6,7 +6,7 @@ use arithmetic::{evaluate_opt, VirtualPolynomial};
use ark_ec::PairingEngine; use ark_ff::PrimeField; use ark_poly::DenseMultilinearExtension; -use std::{borrow::Borrow, rc::Rc}; +use std::{borrow::Borrow, sync::Arc}; use subroutines::pcs::{prelude::Commitment, PolynomialCommitmentScheme}; use transcript::IOPTranscript;@@ -32,7 +32,7 @@ where
E: PairingEngine, PCS: PolynomialCommitmentScheme< E, - Polynomial = Rc<DenseMultilinearExtension<E::Fr>>, + Polynomial = Arc<DenseMultilinearExtension<E::Fr>>, Point = Vec<E::Fr>, Evaluation = E::Fr, Commitment = Commitment<E>,@@ -104,7 +104,7 @@ let mut cur_coeffs = Vec::new();
for row in $rows.iter() { cur_coeffs.push(row.0[i]) } - res.push(Rc::new(DenseMultilinearExtension::from_evaluations_vec( + res.push(Arc::new(DenseMultilinearExtension::from_evaluations_vec( num_vars, cur_coeffs, ))) }@@ -178,8 +178,8 @@ /// vanilla plonk
pub(crate) fn build_f<F: PrimeField>( gates: &CustomizedGates, num_vars: usize, - selector_mles: &[Rc<DenseMultilinearExtension<F>>], - witness_mles: &[Rc<DenseMultilinearExtension<F>>], + selector_mles: &[Arc<DenseMultilinearExtension<F>>], + witness_mles: &[Arc<DenseMultilinearExtension<F>>], ) -> Result<VirtualPolynomial<F>, HyperPlonkErrors> { // TODO: check that selector and witness lengths match what is in // the gate definition@@ -306,7 +306,7 @@ // 0, 1 |-> 2
// 1, 0 |-> 0 // 1, 1 |-> 5 let ql_eval = vec![F::zero(), F::from(2u64), F::zero(), F::from(5u64)]; - let ql = Rc::new(DenseMultilinearExtension::from_evaluations_vec(2, ql_eval)); + let ql = Arc::new(DenseMultilinearExtension::from_evaluations_vec(2, ql_eval)); // W1 = x1x2 + x1 whose evaluations are // 0, 0 |-> 0@@ -314,7 +314,7 @@ // 0, 1 |-> 0
// 1, 0 |-> 1 // 1, 1 |-> 2 let w_eval = vec![F::zero(), F::zero(), F::from(1u64), F::from(2u64)]; - let w1 = Rc::new(DenseMultilinearExtension::from_evaluations_vec(2, w_eval)); + let w1 = Arc::new(DenseMultilinearExtension::from_evaluations_vec(2, w_eval)); // W2 = x1 + x2 whose evaluations are // 0, 0 |-> 0@@ -322,7 +322,7 @@ // 0, 1 |-> 1
// 1, 0 |-> 1 // 1, 1 |-> 2 let w_eval = vec![F::zero(), F::one(), F::from(1u64), F::from(2u64)]; - let w2 = Rc::new(DenseMultilinearExtension::from_evaluations_vec(2, w_eval)); + let w2 = Arc::new(DenseMultilinearExtension::from_evaluations_vec(2, w_eval)); // Example: // q_L(X) * W_1(X)^5 - W_2(X)
@@ -2,7 +2,7 @@ use crate::{build_mle, errors::HyperPlonkErrors};
use ark_ff::PrimeField; use ark_poly::DenseMultilinearExtension; use ark_std::log2; -use std::rc::Rc; +use std::sync::Arc; /// A row of witnesses of width `#wires` #[derive(Debug, Clone)]@@ -71,7 +71,7 @@ ///
/// output mle(a1,b1,c1, ...), mle(a2,b2,c2, ...), ... pub fn build_mles( matrix: &[Self], - ) -> Result<Vec<Rc<DenseMultilinearExtension<F>>>, HyperPlonkErrors> { + ) -> Result<Vec<Arc<DenseMultilinearExtension<F>>>, HyperPlonkErrors> { build_mle!(matrix) } }
@@ -2,7 +2,7 @@ use arithmetic::{identity_permutation_mles, VPAuxInfo, VirtualPolynomial};
use ark_bls12_381::{Bls12_381, Fr}; use ark_poly::{DenseMultilinearExtension, MultilinearExtension}; use ark_std::test_rng; -use std::{marker::PhantomData, rc::Rc, time::Instant}; +use std::{marker::PhantomData, sync::Arc, time::Instant}; use subroutines::{ pcs::{prelude::MultilinearKzgPCS, PolynomialCommitmentScheme}, poly_iop::prelude::{@@ -144,7 +144,7 @@ } else {
10 }; - let ws = vec![Rc::new(DenseMultilinearExtension::rand(nv, &mut rng))]; + let ws = vec![Arc::new(DenseMultilinearExtension::rand(nv, &mut rng))]; // identity map let perms = identity_permutation_mles(nv, 1);@@ -218,8 +218,8 @@
let f: DenseMultilinearExtension<Fr> = DenseMultilinearExtension::rand(nv, &mut rng); let mut g = f.clone(); g.evaluations.reverse(); - let fs = vec![Rc::new(f)]; - let gs = vec![Rc::new(g)]; + let fs = vec![Arc::new(f)]; + let gs = vec![Arc::new(g)]; let proof = { let start = Instant::now();
@@ -1,7 +1,7 @@
use ark_bls12_381::{Bls12_381, Fr}; use ark_ff::UniformRand; use ark_poly::{DenseMultilinearExtension, MultilinearExtension}; -use ark_std::{rc::Rc, test_rng}; +use ark_std::{sync::Arc, test_rng}; use std::time::Instant; use subroutines::pcs::{ prelude::{MultilinearKzgPCS, PCSError, PolynomialCommitmentScheme},@@ -27,7 +27,7 @@ } else {
2 }; - let poly = Rc::new(DenseMultilinearExtension::rand(nv, &mut rng)); + let poly = Arc::new(DenseMultilinearExtension::rand(nv, &mut rng)); let (ck, vk) = uni_params.trim(nv)?; let point: Vec<_> = (0..nv).map(|_| Fr::rand(&mut rng)).collect();
@@ -17,19 +17,13 @@ /// This trait defines APIs for polynomial commitment schemes.
/// Note that for our usage of PCS, we do not require the hiding property. pub trait PolynomialCommitmentScheme<E: PairingEngine> { /// Prover parameters - type ProverParam: Clone; + type ProverParam: Clone + Sync; /// Verifier parameters type VerifierParam: Clone + CanonicalSerialize + CanonicalDeserialize; /// Structured reference string type SRS: Clone + Debug; /// Polynomial and its associated types - type Polynomial: Clone - + Debug - + Hash - + PartialEq - + Eq - + CanonicalSerialize - + CanonicalDeserialize; + type Polynomial: Clone + Debug + Hash + PartialEq + Eq; /// Polynomial input domain type Point: Clone + Ord + Debug + Sync + Hash + PartialEq + Eq; /// Polynomial Evaluation
@@ -17,7 +17,8 @@ use arithmetic::{build_eq_x_r_vec, DenseMultilinearExtension, VPAuxInfo, VirtualPolynomial};
use ark_ec::{msm::VariableBaseMSM, PairingEngine, ProjectiveCurve}; use ark_ff::PrimeField; use ark_std::{end_timer, log2, start_timer, One, Zero}; -use std::{marker::PhantomData, rc::Rc}; +use rayon::prelude::{IntoParallelRefIterator, ParallelIterator}; +use std::{marker::PhantomData, sync::Arc}; use transcript::IOPTranscript; #[derive(Clone, Debug, Default, PartialEq, Eq)]@@ -53,7 +54,7 @@ where
E: PairingEngine, PCS: PolynomialCommitmentScheme< E, - Polynomial = Rc<DenseMultilinearExtension<E::Fr>>, + Polynomial = Arc<DenseMultilinearExtension<E::Fr>>, Point = Vec<E::Fr>, Evaluation = E::Fr, >,@@ -79,7 +80,7 @@ let mut tilde_g_eval = vec![E::Fr::zero(); 1 << num_var];
for (j, &f_i_eval) in f_i.iter().enumerate() { tilde_g_eval[j] = f_i_eval * eq_t_i_list[index]; } - tilde_gs.push(Rc::new(DenseMultilinearExtension::from_evaluations_vec( + tilde_gs.push(Arc::new(DenseMultilinearExtension::from_evaluations_vec( num_var, tilde_g_eval, )));@@ -87,13 +88,15 @@ }
end_timer!(timer); let timer = start_timer!(|| format!("compute tilde eq for {} points", points.len())); - let mut tilde_eqs = vec![]; - for point in points.iter() { - let eq_b_zi = build_eq_x_r_vec(point)?; - tilde_eqs.push(Rc::new(DenseMultilinearExtension::from_evaluations_vec( - num_var, eq_b_zi, - ))); - } + let tilde_eqs: Vec<Arc<DenseMultilinearExtension<<E as PairingEngine>::Fr>>> = points + .par_iter() + .map(|point| { + let eq_b_zi = build_eq_x_r_vec(point).unwrap(); + Arc::new(DenseMultilinearExtension::from_evaluations_vec( + num_var, eq_b_zi, + )) + }) + .collect(); end_timer!(timer); // built the virtual polynomial for SumCheck@@ -131,7 +134,7 @@ for (j, &tilde_g_eval) in tilde_g.iter().enumerate() {
g_prime_evals[j] += tilde_g_eval * eq_i_a2; } } - let g_prime = Rc::new(DenseMultilinearExtension::from_evaluations_vec( + let g_prime = Arc::new(DenseMultilinearExtension::from_evaluations_vec( num_var, g_prime_evals, ));@@ -169,7 +172,7 @@ where
E: PairingEngine, PCS: PolynomialCommitmentScheme< E, - Polynomial = Rc<DenseMultilinearExtension<E::Fr>>, + Polynomial = Arc<DenseMultilinearExtension<E::Fr>>, Point = Vec<E::Fr>, Evaluation = E::Fr, Commitment = Commitment<E>,@@ -265,7 +268,7 @@ type Fr = <E as PairingEngine>::Fr;
fn test_multi_open_helper<R: RngCore + CryptoRng>( ml_params: &MultilinearUniversalParams<E>, - polys: &[Rc<DenseMultilinearExtension<Fr>>], + polys: &[Arc<DenseMultilinearExtension<Fr>>], rng: &mut R, ) -> Result<(), PCSError> { let merged_nv = get_batched_nv(polys[0].num_vars(), polys.len());@@ -323,7 +326,7 @@ let ml_params = MultilinearUniversalParams::<E>::gen_srs_for_testing(&mut rng, 20)?;
for num_poly in 5..6 { for nv in 15..16 { let polys1: Vec<_> = (0..num_poly) - .map(|_| Rc::new(DenseMultilinearExtension::rand(nv, &mut rng))) + .map(|_| Arc::new(DenseMultilinearExtension::rand(nv, &mut rng))) .collect(); test_multi_open_helper(&ml_params, &polys1, &mut rng)?; }
@@ -27,9 +27,9 @@ borrow::Borrow,
end_timer, format, marker::PhantomData, rand::{CryptoRng, RngCore}, - rc::Rc, start_timer, string::ToString, + sync::Arc, vec, vec::Vec, One, Zero,@@ -59,7 +59,7 @@ type ProverParam = MultilinearProverParam<E>;
type VerifierParam = MultilinearVerifierParam<E>; type SRS = MultilinearUniversalParams<E>; // Polynomial and its associated types - type Polynomial = Rc<DenseMultilinearExtension<E::Fr>>; + type Polynomial = Arc<DenseMultilinearExtension<E::Fr>>; type Point = Vec<E::Fr>; type Evaluation = E::Fr; // Commitments and proofs@@ -356,7 +356,7 @@ type Fr = <E as PairingEngine>::Fr;
fn test_single_helper<R: RngCore + CryptoRng>( params: &MultilinearUniversalParams<E>, - poly: &Rc<DenseMultilinearExtension<Fr>>, + poly: &Arc<DenseMultilinearExtension<Fr>>, rng: &mut R, ) -> Result<(), PCSError> { let nv = poly.num_vars();@@ -385,11 +385,11 @@
let params = MultilinearKzgPCS::<E>::gen_srs_for_testing(&mut rng, 10)?; // normal polynomials - let poly1 = Rc::new(DenseMultilinearExtension::rand(8, &mut rng)); + let poly1 = Arc::new(DenseMultilinearExtension::rand(8, &mut rng)); test_single_helper(¶ms, &poly1, &mut rng)?; // single-variate polynomials - let poly2 = Rc::new(DenseMultilinearExtension::rand(1, &mut rng)); + let poly2 = Arc::new(DenseMultilinearExtension::rand(1, &mut rng)); test_single_helper(¶ms, &poly2, &mut rng)?; Ok(())
@@ -8,7 +8,7 @@ };
use ark_ec::PairingEngine; use ark_poly::DenseMultilinearExtension; use ark_std::{end_timer, start_timer}; -use std::rc::Rc; +use std::sync::Arc; use transcript::IOPTranscript; /// A permutation subclaim consists of@@ -95,7 +95,7 @@
impl<E, PCS> PermutationCheck<E, PCS> for PolyIOP<E::Fr> where E: PairingEngine, - PCS: PolynomialCommitmentScheme<E, Polynomial = Rc<DenseMultilinearExtension<E::Fr>>>, + PCS: PolynomialCommitmentScheme<E, Polynomial = Arc<DenseMultilinearExtension<E::Fr>>>, { type PermutationCheckSubClaim = PermutationCheckSubClaim<E, PCS, Self>; type PermutationProof = Self::ProductCheckProof;@@ -192,19 +192,19 @@ use ark_bls12_381::Bls12_381;
use ark_ec::PairingEngine; use ark_poly::{DenseMultilinearExtension, MultilinearExtension}; use ark_std::test_rng; - use std::{marker::PhantomData, rc::Rc}; + use std::{marker::PhantomData, sync::Arc}; type KZG = MultilinearKzgPCS<Bls12_381>; fn test_permutation_check_helper<E, PCS>( pcs_param: &PCS::ProverParam, - fxs: &[Rc<DenseMultilinearExtension<E::Fr>>], - gxs: &[Rc<DenseMultilinearExtension<E::Fr>>], - perms: &[Rc<DenseMultilinearExtension<E::Fr>>], + fxs: &[Arc<DenseMultilinearExtension<E::Fr>>], + gxs: &[Arc<DenseMultilinearExtension<E::Fr>>], + perms: &[Arc<DenseMultilinearExtension<E::Fr>>], ) -> Result<(), PolyIOPErrors> where E: PairingEngine, - PCS: PolynomialCommitmentScheme<E, Polynomial = Rc<DenseMultilinearExtension<E::Fr>>>, + PCS: PolynomialCommitmentScheme<E, Polynomial = Arc<DenseMultilinearExtension<E::Fr>>>, { let nv = fxs[0].num_vars; // what's AuxInfo used for?@@ -257,8 +257,8 @@ {
// good path: (w1, w2) is a permutation of (w1, w2) itself under the identify // map let ws = vec![ - Rc::new(DenseMultilinearExtension::rand(nv, &mut rng)), - Rc::new(DenseMultilinearExtension::rand(nv, &mut rng)), + Arc::new(DenseMultilinearExtension::rand(nv, &mut rng)), + Arc::new(DenseMultilinearExtension::rand(nv, &mut rng)), ]; // perms is the identity map test_permutation_check_helper::<Bls12_381, KZG>(&pcs_param, &ws, &ws, &id_perms)?;@@ -267,8 +267,8 @@
{ // good path: f = (w1, w2) is a permutation of g = (w2, w1) itself under a map let mut fs = vec![ - Rc::new(DenseMultilinearExtension::rand(nv, &mut rng)), - Rc::new(DenseMultilinearExtension::rand(nv, &mut rng)), + Arc::new(DenseMultilinearExtension::rand(nv, &mut rng)), + Arc::new(DenseMultilinearExtension::rand(nv, &mut rng)), ]; let gs = fs.clone(); fs.reverse();@@ -281,8 +281,8 @@
{ // bad path 1: w is a not permutation of w itself under a random map let ws = vec![ - Rc::new(DenseMultilinearExtension::rand(nv, &mut rng)), - Rc::new(DenseMultilinearExtension::rand(nv, &mut rng)), + Arc::new(DenseMultilinearExtension::rand(nv, &mut rng)), + Arc::new(DenseMultilinearExtension::rand(nv, &mut rng)), ]; // perms is a random map let perms = random_permutation_mles(nv, 2, &mut rng);@@ -296,12 +296,12 @@
{ // bad path 2: f is a not permutation of g under a identity map let fs = vec![ - Rc::new(DenseMultilinearExtension::rand(nv, &mut rng)), - Rc::new(DenseMultilinearExtension::rand(nv, &mut rng)), + Arc::new(DenseMultilinearExtension::rand(nv, &mut rng)), + Arc::new(DenseMultilinearExtension::rand(nv, &mut rng)), ]; let gs = vec![ - Rc::new(DenseMultilinearExtension::rand(nv, &mut rng)), - Rc::new(DenseMultilinearExtension::rand(nv, &mut rng)), + Arc::new(DenseMultilinearExtension::rand(nv, &mut rng)), + Arc::new(DenseMultilinearExtension::rand(nv, &mut rng)), ]; // s_perm is the identity map
@@ -5,7 +5,7 @@ use arithmetic::identity_permutation_mles;
use ark_ff::PrimeField; use ark_poly::DenseMultilinearExtension; use ark_std::{end_timer, start_timer}; -use std::rc::Rc; +use std::sync::Arc; /// Returns the evaluations of two list of MLEs: /// - numerators = (a1, ..., ak)@@ -24,13 +24,13 @@ #[allow(clippy::type_complexity)]
pub(super) fn computer_nums_and_denoms<F: PrimeField>( beta: &F, gamma: &F, - fxs: &[Rc<DenseMultilinearExtension<F>>], - gxs: &[Rc<DenseMultilinearExtension<F>>], - perms: &[Rc<DenseMultilinearExtension<F>>], + fxs: &[Arc<DenseMultilinearExtension<F>>], + gxs: &[Arc<DenseMultilinearExtension<F>>], + perms: &[Arc<DenseMultilinearExtension<F>>], ) -> Result< ( - Vec<Rc<DenseMultilinearExtension<F>>>, - Vec<Rc<DenseMultilinearExtension<F>>>, + Vec<Arc<DenseMultilinearExtension<F>>>, + Vec<Arc<DenseMultilinearExtension<F>>>, ), PolyIOPErrors, > {@@ -54,11 +54,11 @@
numerator_evals.push(numerator); denominator_evals.push(denominator); } - numerators.push(Rc::new(DenseMultilinearExtension::from_evaluations_vec( + numerators.push(Arc::new(DenseMultilinearExtension::from_evaluations_vec( num_vars, numerator_evals, ))); - denominators.push(Rc::new(DenseMultilinearExtension::from_evaluations_vec( + denominators.push(Arc::new(DenseMultilinearExtension::from_evaluations_vec( num_vars, denominator_evals, )));
@@ -14,7 +14,7 @@ use ark_ec::PairingEngine;
use ark_ff::{One, PrimeField, Zero}; use ark_poly::DenseMultilinearExtension; use ark_std::{end_timer, start_timer}; -use std::rc::Rc; +use std::sync::Arc; use transcript::IOPTranscript; mod util;@@ -142,7 +142,7 @@
impl<E, PCS> ProductCheck<E, PCS> for PolyIOP<E::Fr> where E: PairingEngine, - PCS: PolynomialCommitmentScheme<E, Polynomial = Rc<DenseMultilinearExtension<E::Fr>>>, + PCS: PolynomialCommitmentScheme<E, Polynomial = Arc<DenseMultilinearExtension<E::Fr>>>, { type ProductCheckSubClaim = ProductCheckSubClaim<E::Fr, Self>; type ProductCheckProof = ProductCheckProof<E, PCS, Self>;@@ -257,12 +257,12 @@ use ark_bls12_381::{Bls12_381, Fr};
use ark_ec::PairingEngine; use ark_poly::{DenseMultilinearExtension, MultilinearExtension}; use ark_std::test_rng; - use std::{marker::PhantomData, rc::Rc}; + use std::{marker::PhantomData, sync::Arc}; fn check_frac_poly<E>( - frac_poly: &Rc<DenseMultilinearExtension<E::Fr>>, - fs: &[Rc<DenseMultilinearExtension<E::Fr>>], - gs: &[Rc<DenseMultilinearExtension<E::Fr>>], + frac_poly: &Arc<DenseMultilinearExtension<E::Fr>>, + fs: &[Arc<DenseMultilinearExtension<E::Fr>>], + gs: &[Arc<DenseMultilinearExtension<E::Fr>>], ) where E: PairingEngine, {@@ -285,14 +285,14 @@ }
// fs and gs are guaranteed to have the same product // fs and hs doesn't have the same product fn test_product_check_helper<E, PCS>( - fs: &[Rc<DenseMultilinearExtension<E::Fr>>], - gs: &[Rc<DenseMultilinearExtension<E::Fr>>], - hs: &[Rc<DenseMultilinearExtension<E::Fr>>], + fs: &[Arc<DenseMultilinearExtension<E::Fr>>], + gs: &[Arc<DenseMultilinearExtension<E::Fr>>], + hs: &[Arc<DenseMultilinearExtension<E::Fr>>], pcs_param: &PCS::ProverParam, ) -> Result<(), PolyIOPErrors> where E: PairingEngine, - PCS: PolynomialCommitmentScheme<E, Polynomial = Rc<DenseMultilinearExtension<E::Fr>>>, + PCS: PolynomialCommitmentScheme<E, Polynomial = Arc<DenseMultilinearExtension<E::Fr>>>, { let mut transcript = <PolyIOP<E::Fr> as ProductCheck<E, PCS>>::init_transcript(); transcript.append_message(b"testing", b"initializing transcript for testing")?;@@ -352,11 +352,11 @@ g1.evaluations.reverse();
let f2: DenseMultilinearExtension<Fr> = DenseMultilinearExtension::rand(nv, &mut rng); let mut g2 = f2.clone(); g2.evaluations.reverse(); - let fs = vec![Rc::new(f1), Rc::new(f2)]; - let gs = vec![Rc::new(g2), Rc::new(g1)]; + let fs = vec![Arc::new(f1), Arc::new(f2)]; + let gs = vec![Arc::new(g2), Arc::new(g1)]; let mut hs = vec![]; for _ in 0..fs.len() { - hs.push(Rc::new(DenseMultilinearExtension::rand( + hs.push(Arc::new(DenseMultilinearExtension::rand( fs[0].num_vars, &mut rng, )));
@@ -2,10 +2,10 @@ //! This module implements useful functions for the product check protocol.
use crate::poly_iop::{errors::PolyIOPErrors, structs::IOPProof, zero_check::ZeroCheck, PolyIOP}; use arithmetic::{get_index, VirtualPolynomial}; -use ark_ff::PrimeField; +use ark_ff::{batch_inversion, PrimeField}; use ark_poly::DenseMultilinearExtension; use ark_std::{end_timer, start_timer}; -use std::rc::Rc; +use std::sync::Arc; use transcript::IOPTranscript; /// Compute multilinear fractional polynomial s.t. frac(x) = f1(x) * ... * fk(x)@@ -14,9 +14,9 @@ ///
/// The caller needs to sanity-check that the number of polynomials and /// variables match in fxs and gxs; and gi(x) has no zero entries. pub(super) fn compute_frac_poly<F: PrimeField>( - fxs: &[Rc<DenseMultilinearExtension<F>>], - gxs: &[Rc<DenseMultilinearExtension<F>>], -) -> Result<Rc<DenseMultilinearExtension<F>>, PolyIOPErrors> { + fxs: &[Arc<DenseMultilinearExtension<F>>], + gxs: &[Arc<DenseMultilinearExtension<F>>], +) -> Result<Arc<DenseMultilinearExtension<F>>, PolyIOPErrors> { let start = start_timer!(|| "compute frac(x)"); let mut f_evals = vec![F::one(); 1 << fxs[0].num_vars];@@ -31,17 +31,19 @@ for (g_eval, gi) in g_evals.iter_mut().zip(gx.iter()) {
*g_eval *= gi; } } + batch_inversion(&mut g_evals[..]); + for (f_eval, g_eval) in f_evals.iter_mut().zip(g_evals.iter()) { if *g_eval == F::zero() { return Err(PolyIOPErrors::InvalidParameters( "gxs has zero entries in the boolean hypercube".to_string(), )); } - *f_eval /= g_eval; + *f_eval *= g_eval; } end_timer!(start); - Ok(Rc::new(DenseMultilinearExtension::from_evaluations_vec( + Ok(Arc::new(DenseMultilinearExtension::from_evaluations_vec( fxs[0].num_vars, f_evals, )))@@ -55,8 +57,8 @@ ///
/// The caller needs to check num_vars matches in f and g /// Cost: linear in N. pub(super) fn compute_product_poly<F: PrimeField>( - frac_poly: &Rc<DenseMultilinearExtension<F>>, -) -> Result<Rc<DenseMultilinearExtension<F>>, PolyIOPErrors> { + frac_poly: &Arc<DenseMultilinearExtension<F>>, +) -> Result<Arc<DenseMultilinearExtension<F>>, PolyIOPErrors> { let start = start_timer!(|| "compute evaluations of prod polynomial"); let num_vars = frac_poly.num_vars; let frac_evals = &frac_poly.evaluations;@@ -96,7 +98,7 @@ // prod(1, 1, ..., 1) := 0
prod_x_evals.push(F::zero()); end_timer!(start); - Ok(Rc::new(DenseMultilinearExtension::from_evaluations_vec( + Ok(Arc::new(DenseMultilinearExtension::from_evaluations_vec( num_vars, prod_x_evals, )))@@ -111,10 +113,10 @@ /// Returns proof.
/// /// Cost: O(N) pub(super) fn prove_zero_check<F: PrimeField>( - fxs: &[Rc<DenseMultilinearExtension<F>>], - gxs: &[Rc<DenseMultilinearExtension<F>>], - frac_poly: &Rc<DenseMultilinearExtension<F>>, - prod_x: &Rc<DenseMultilinearExtension<F>>, + fxs: &[Arc<DenseMultilinearExtension<F>>], + gxs: &[Arc<DenseMultilinearExtension<F>>], + frac_poly: &Arc<DenseMultilinearExtension<F>>, + prod_x: &Arc<DenseMultilinearExtension<F>>, alpha: &F, transcript: &mut IOPTranscript<F>, ) -> Result<(IOPProof<F>, VirtualPolynomial<F>), PolyIOPErrors> {@@ -135,10 +137,10 @@ p1_evals[x] = prod_x.evaluations[x0];
p2_evals[x] = prod_x.evaluations[x1]; } } - let p1 = Rc::new(DenseMultilinearExtension::from_evaluations_vec( + let p1 = Arc::new(DenseMultilinearExtension::from_evaluations_vec( num_vars, p1_evals, )); - let p2 = Rc::new(DenseMultilinearExtension::from_evaluations_vec( + let p2 = Arc::new(DenseMultilinearExtension::from_evaluations_vec( num_vars, p2_evals, ));
@@ -9,7 +9,7 @@ use arithmetic::{VPAuxInfo, VirtualPolynomial};
use ark_ff::PrimeField; use ark_poly::DenseMultilinearExtension; use ark_std::{end_timer, start_timer}; -use std::{fmt::Debug, rc::Rc}; +use std::{fmt::Debug, sync::Arc}; use transcript::IOPTranscript; mod prover;@@ -127,7 +127,7 @@ impl<F: PrimeField> SumCheck<F> for PolyIOP<F> {
type SumCheckProof = IOPProof<F>; type VirtualPolynomial = VirtualPolynomial<F>; type VPAuxInfo = VPAuxInfo<F>; - type MultilinearExtension = Rc<DenseMultilinearExtension<F>>; + type MultilinearExtension = Arc<DenseMultilinearExtension<F>>; type SumCheckSubClaim = SumCheckSubClaim<F>; type Transcript = IOPTranscript<F>;@@ -210,7 +210,7 @@ use ark_bls12_381::Fr;
use ark_ff::UniformRand; use ark_poly::{DenseMultilinearExtension, MultilinearExtension}; use ark_std::test_rng; - use std::rc::Rc; + use std::sync::Arc; fn test_sumcheck( nv: usize,@@ -326,7 +326,7 @@ /// unique MLExtensions instead of total number of multiplicands.
fn test_shared_reference() -> Result<(), PolyIOPErrors> { let mut rng = test_rng(); let ml_extensions: Vec<_> = (0..5) - .map(|_| Rc::new(DenseMultilinearExtension::<Fr>::rand(8, &mut rng))) + .map(|_| Arc::new(DenseMultilinearExtension::<Fr>::rand(8, &mut rng))) .collect(); let mut poly = VirtualPolynomial::new(8); poly.add_mle_list(
@@ -9,8 +9,8 @@ use arithmetic::{fix_variables, VirtualPolynomial};
use ark_ff::PrimeField; use ark_poly::DenseMultilinearExtension; use ark_std::{end_timer, start_timer, vec::Vec}; -use rayon::prelude::IntoParallelIterator; -use std::rc::Rc; +use rayon::prelude::{IntoParallelIterator, IntoParallelRefIterator}; +use std::sync::Arc; #[cfg(feature = "parallel")] use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator};@@ -71,7 +71,7 @@ // eval g over r_m, and mutate g to g(r_1, ... r_m,, x_{m+1}... x_n)
let mut flattened_ml_extensions: Vec<DenseMultilinearExtension<F>> = self .poly .flattened_ml_extensions - .iter() + .par_iter() .map(|x| x.as_ref().clone()) .collect();@@ -132,13 +132,11 @@ * (table1[(b << 1) + 1] + table1[(b << 1) + 1] - table1[b << 1])
} }) .collect::<Vec<F>>(); - for val in evals.iter() { - *e += val - } + *e += evals.par_iter().sum::<F>(); } } else { for (t, e) in products_sum.iter_mut().enumerate() { - let t = F::from(t as u64); + let t = F::from(t as u128); let products = (0..1 << (self.poly.aux_info.num_variables - self.round)) .into_par_iter() .map(|b| {@@ -149,6 +147,9 @@ let num_mles = products.len();
let mut product = *coefficient; for &f in products.iter().take(num_mles) { let table = &flattened_ml_extensions[f]; // f's range is checked in init + // TODO: Could be done faster by cashing the results from the + // previous t and adding the diff + // Also possible to use Karatsuba multiplication product *= table[b << 1] + (table[(b << 1) + 1] - table[b << 1]) * t; }@@ -158,10 +159,7 @@
tmp }) .collect::<Vec<F>>(); - - for i in products.iter() { - *e += i - } + *e += products.par_iter().sum::<F>(); } } }@@ -187,8 +185,8 @@ });
// update prover's state to the partial evaluated polynomial self.poly.flattened_ml_extensions = flattened_ml_extensions - .iter() - .map(|x| Rc::new(x.clone())) + .par_iter() + .map(|x| Arc::new(x.clone())) .collect(); // end_timer!(compute_sum);