From c982826e04247b31c022b47c808d315ddfe511fe Mon Sep 17 00:00:00 2001 From: onsen-egg Date: Thu, 6 Jul 2023 12:39:11 -0500 Subject: [PATCH 1/3] Add feature "rc" to serde crate import --- plonky2/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plonky2/Cargo.toml b/plonky2/Cargo.toml index 39b95f21..0f2438fd 100644 --- a/plonky2/Cargo.toml +++ b/plonky2/Cargo.toml @@ -30,7 +30,7 @@ plonky2_field = { version = "0.1.0", default-features = false } plonky2_util = { version = "0.1.0", default-features = false } rand = { version = "0.8.4", default-features = false } rand_chacha = { version = "0.3.1", optional = true, default-features = false } -serde = { version = "1.0", default-features = false, features = ["derive"] } +serde = { version = "1.0", default-features = false, features = ["derive", "rc"] } serde_json = "1.0" static_assertions = { version = "1.1.0", default-features = false } unroll = { version = "0.1.5", default-features = false } From 03d90f30c96bca44fd57f7975d5be01cf25d0942 Mon Sep 17 00:00:00 2001 From: onsen-egg Date: Tue, 23 May 2023 10:12:38 -0400 Subject: [PATCH 2/3] Faster multiplicity counting for lookup tables --- plonky2/src/plonk/prover.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/plonky2/src/plonk/prover.rs b/plonky2/src/plonk/prover.rs index df2249df..3748e68b 100644 --- a/plonky2/src/plonk/prover.rs +++ b/plonky2/src/plonk/prover.rs @@ -4,6 +4,7 @@ use core::cmp::min; use core::mem::swap; use anyhow::{ensure, Result}; +use hashbrown::HashMap; use plonky2_maybe_rayon::*; use super::circuit_builder::{LookupChallenges, LookupWire}; @@ -58,13 +59,18 @@ pub fn set_lookup_wires< // Compute multiplicities. let mut multiplicities = vec![0; lut_len]; + + let table_value_to_idx: HashMap = common_data.luts[lut_index] + .iter() + .enumerate() + .map(|(i, (inp_target, _))| (inp_target.clone(), i)) + .collect(); + for (inp_target, _) in prover_data.lut_to_lookups[lut_index].iter() { let inp_value = pw.get_target(*inp_target); - let mut idx = 0; - while F::from_canonical_u16(common_data.luts[lut_index][idx].0) != inp_value { - idx += 1; - } - multiplicities[idx] += 1; + let idx = table_value_to_idx.get(&u16::try_from(inp_value.to_canonical_u64()).unwrap()).unwrap(); + + multiplicities[*idx] += 1; } // Pad the last `LookupGate` with the first entry from the LUT. From a67cfdcb676b8637110621a8fe35251f0c583ec7 Mon Sep 17 00:00:00 2001 From: onsen-egg Date: Wed, 24 May 2023 19:45:38 -0400 Subject: [PATCH 3/3] Precompute RE poly evals for challenges --- plonky2/src/plonk/prover.rs | 45 +++++++++++++++++++++++++++-- plonky2/src/plonk/vanishing_poly.rs | 21 +++++--------- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/plonky2/src/plonk/prover.rs b/plonky2/src/plonk/prover.rs index 3748e68b..2a58e6b4 100644 --- a/plonky2/src/plonk/prover.rs +++ b/plonky2/src/plonk/prover.rs @@ -15,6 +15,7 @@ use crate::field::zero_poly_coset::ZeroPolyOnCoset; use crate::fri::oracle::PolynomialBatch; use crate::gates::lookup::LookupGate; use crate::gates::lookup_table::LookupTableGate; +use crate::gates::selectors::LookupSelectors; use crate::hash::hash_types::RichField; use crate::iop::challenger::Challenger; use crate::iop::generator::generate_partial_witness; @@ -25,7 +26,7 @@ use crate::plonk::circuit_data::{CommonCircuitData, ProverOnlyCircuitData}; use crate::plonk::config::{GenericConfig, Hasher}; use crate::plonk::plonk_common::PlonkOracle; use crate::plonk::proof::{OpeningSet, Proof, ProofWithPublicInputs}; -use crate::plonk::vanishing_poly::eval_vanishing_poly_base_batch; +use crate::plonk::vanishing_poly::{eval_vanishing_poly_base_batch, get_lut_poly}; use crate::plonk::vars::EvaluationVarsBaseBatch; use crate::timed; use crate::util::partial_products::{partial_products_and_z_gx, quotient_chunk_products}; @@ -68,7 +69,9 @@ pub fn set_lookup_wires< for (inp_target, _) in prover_data.lut_to_lookups[lut_index].iter() { let inp_value = pw.get_target(*inp_target); - let idx = table_value_to_idx.get(&u16::try_from(inp_value.to_canonical_u64()).unwrap()).unwrap(); + let idx = table_value_to_idx + .get(&u16::try_from(inp_value.to_canonical_u64()).unwrap()) + .unwrap(); multiplicities[*idx] += 1; } @@ -618,8 +621,45 @@ fn compute_quotient_polys< let z_h_on_coset = ZeroPolyOnCoset::new(common_data.degree_bits(), quotient_degree_bits); + // Precompute the lookup table evals on the challenges in delta + // These values are used to produce the final RE constraints for each lut, + // and are the same each time in check_lookup_constraints_batched. + // lut_poly_evals[i][j] gives the eval for the i'th challenge and the j'th lookup table + let lut_re_poly_evals: Vec> = if has_lookup { + let num_lut_slots = LookupTableGate::num_slots(&common_data.config); + (0..num_challenges) + .map(move |i| { + let cur_deltas = &deltas[NUM_COINS_LOOKUP * i..NUM_COINS_LOOKUP * (i + 1)]; + let cur_challenge_delta = cur_deltas[LookupChallenges::ChallengeDelta as usize]; + + (LookupSelectors::StartEnd as usize..common_data.num_lookup_selectors) + .map(|r| { + let lut_row_number = ceil_div_usize( + common_data.luts[r - LookupSelectors::StartEnd as usize].len(), + num_lut_slots, + ); + + get_lut_poly( + common_data, + r - LookupSelectors::StartEnd as usize, + cur_deltas, + num_lut_slots * lut_row_number, + ) + .eval(cur_challenge_delta) + }) + .collect() + }) + .collect() + } else { + vec![] + }; + + let lut_re_poly_evals_refs: Vec<&[F]> = + lut_re_poly_evals.iter().map(|v| v.as_slice()).collect(); + let points_batches = points.par_chunks(BATCH_SIZE); let num_batches = ceil_div_usize(points.len(), BATCH_SIZE); + let quotient_values: Vec> = points_batches .enumerate() .flat_map(|(batch_i, xs_batch)| { @@ -729,6 +769,7 @@ fn compute_quotient_polys< deltas, alphas, &z_h_on_coset, + &lut_re_poly_evals_refs, ); for (&i, quotient_values) in indices_batch.iter().zip(quotient_values_batch.iter_mut()) diff --git a/plonky2/src/plonk/vanishing_poly.rs b/plonky2/src/plonk/vanishing_poly.rs index adc76654..4708cddd 100644 --- a/plonky2/src/plonk/vanishing_poly.rs +++ b/plonky2/src/plonk/vanishing_poly.rs @@ -177,6 +177,7 @@ pub(crate) fn eval_vanishing_poly_base_batch, const deltas: &[F], alphas: &[F], z_h_on_coset: &ZeroPolyOnCoset, + lut_re_poly_evals: &[&[F]], ) -> Vec> { let has_lookup = common_data.num_lookup_polys != 0; @@ -276,6 +277,7 @@ pub(crate) fn eval_vanishing_poly_base_batch, const cur_next_lookup_zs, &lookup_selectors, cur_deltas.try_into().unwrap(), + lut_re_poly_evals[i], ); vanishing_all_lookup_terms.extend(lookup_constraints); } @@ -514,6 +516,7 @@ pub fn check_lookup_constraints_batch, const D: usi next_lookup_zs: &[F], lookup_selectors: &[F], deltas: &[F; 4], + lut_re_poly_evals: &[F], ) -> Vec { let num_lu_slots = LookupGate::num_slots(&common_data.config); let num_lut_slots = LookupTableGate::num_slots(&common_data.config); @@ -568,24 +571,14 @@ pub fn check_lookup_constraints_batch, const D: usi // Check initial RE constraint. constraints.push(lookup_selectors[LookupSelectors::InitSre as usize] * z_re); - let current_delta = deltas[LookupChallenges::ChallengeDelta as usize]; - // Check final RE constraints for each different LUT. for r in LookupSelectors::StartEnd as usize..common_data.num_lookup_selectors { let cur_ends_selector = lookup_selectors[r]; - let lut_row_number = ceil_div_usize( - common_data.luts[r - LookupSelectors::StartEnd as usize].len(), - num_lut_slots, - ); - let cur_function_eval = get_lut_poly( - common_data, - r - LookupSelectors::StartEnd as usize, - deltas, - num_lut_slots * lut_row_number, - ) - .eval(current_delta); - constraints.push(cur_ends_selector * (z_re - cur_function_eval)) + // Use the precomputed value for the lut poly evaluation + let re_poly_eval = lut_re_poly_evals[r - LookupSelectors::StartEnd as usize]; + + constraints.push(cur_ends_selector * (z_re - re_poly_eval)) } // Check RE row transition constraint.