Skip to content

Commit

Permalink
Improve performance of vk & pk keygen and of default parallelize ch…
Browse files Browse the repository at this point in the history
…unking size.

Reduces proving time on large circuits consistently >=3%.
Builts upon [speed up generate vk pk with multi-thread](privacy-scaling-explorations#88)
Fixes: privacy-scaling-explorations#83
  • Loading branch information
pinkiebell committed Jan 18, 2023
1 parent c5e69e6 commit b3a8f24
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 49 deletions.
2 changes: 1 addition & 1 deletion halo2_proofs/src/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ pub fn parallelize<T: Send, F: Fn(&mut [T], usize) + Send + Sync + Clone>(v: &mu
let num_threads = multicore::current_num_threads();
let mut chunk = (n as usize) / num_threads;
if chunk < num_threads {
chunk = n as usize;
chunk = 1;
}

multicore::scope(|scope| {
Expand Down
117 changes: 69 additions & 48 deletions halo2_proofs/src/plonk/permutation/keygen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,39 +122,45 @@ impl Assembly {
}

// Compute [omega_powers * \delta^0, omega_powers * \delta^1, ..., omega_powers * \delta^m]
let mut deltaomega = Vec::with_capacity(p.columns.len());
let mut deltaomega = vec![omega_powers; p.columns.len()];
{
let mut cur = C::Scalar::one();
for _ in 0..p.columns.len() {
let mut omega_powers = omega_powers.clone();
for o in &mut omega_powers {
*o *= &cur;
parallelize(&mut deltaomega, |o, start| {
let mut cur = C::Scalar::DELTA.pow_vartime(&[start as u64]);
for omega_powers in o.iter_mut() {
for v in omega_powers {
*v *= &cur;
}
cur *= &C::Scalar::DELTA;
}
});
}

deltaomega.push(omega_powers);

cur *= &C::Scalar::DELTA;
}
// Computes the permutation polynomial based on the permutation
// description in the assembly.
let mut permutations = vec![domain.empty_lagrange(); p.columns.len()];
{
parallelize(&mut permutations, |o, start| {
for (x, permutation_poly) in o.iter_mut().enumerate() {
let i = start + x;
for (j, p) in permutation_poly.iter_mut().enumerate() {
let (permuted_i, permuted_j) = self.mapping[i][j];
*p = deltaomega[permuted_i][permuted_j];
}
}
});
}

// Pre-compute commitments for the URS.
let mut commitments = vec![];
for i in 0..p.columns.len() {
// Computes the permutation polynomial based on the permutation
// description in the assembly.
let mut permutation_poly = domain.empty_lagrange();
for (j, p) in permutation_poly.iter_mut().enumerate() {
let (permuted_i, permuted_j) = self.mapping[i][j];
*p = deltaomega[permuted_i][permuted_j];
}

let mut commitments = Vec::with_capacity(p.columns.len());
for permutation in &permutations {
// Compute commitment to permutation polynomial
commitments.push(
params
.commit_lagrange(&permutation_poly, Blind::default())
.commit_lagrange(permutation, Blind::default())
.to_affine(),
);
}

VerifyingKey { commitments }
}

Expand All @@ -178,40 +184,55 @@ impl Assembly {
}

// Compute [omega_powers * \delta^0, omega_powers * \delta^1, ..., omega_powers * \delta^m]
let mut deltaomega = Vec::with_capacity(p.columns.len());
let mut deltaomega = vec![omega_powers; p.columns.len()];
{
let mut cur = C::Scalar::one();
for _ in 0..p.columns.len() {
let mut omega_powers = omega_powers.clone();
for o in &mut omega_powers {
*o *= &cur;
parallelize(&mut deltaomega, |o, start| {
let mut cur = C::Scalar::DELTA.pow_vartime(&[start as u64]);
for omega_powers in o.iter_mut() {
for v in omega_powers {
*v *= &cur;
}
cur *= &C::Scalar::DELTA;
}

deltaomega.push(omega_powers);

cur *= &C::Scalar::DELTA;
}
});
}

// Compute permutation polynomials, convert to coset form.
let mut permutations = vec![];
let mut polys = vec![];
let mut cosets = vec![];
for i in 0..p.columns.len() {
// Computes the permutation polynomial based on the permutation
// description in the assembly.
let mut permutation_poly = domain.empty_lagrange();
for (j, p) in permutation_poly.iter_mut().enumerate() {
let (permuted_i, permuted_j) = self.mapping[i][j];
*p = deltaomega[permuted_i][permuted_j];
}
let mut permutations = vec![domain.empty_lagrange(); p.columns.len()];
{
parallelize(&mut permutations, |o, start| {
for (x, permutation_poly) in o.iter_mut().enumerate() {
let i = start + x;
for (j, p) in permutation_poly.iter_mut().enumerate() {
let (permuted_i, permuted_j) = self.mapping[i][j];
*p = deltaomega[permuted_i][permuted_j];
}
}
});
}

let mut polys = vec![domain.empty_coeff(); p.columns.len()];
{
parallelize(&mut polys, |o, start| {
for (x, poly) in o.iter_mut().enumerate() {
let i = start + x;
let permutation_poly = permutations[i].clone();
*poly = domain.lagrange_to_coeff(permutation_poly);
}
});
}

// Store permutation polynomial and precompute its coset evaluation
permutations.push(permutation_poly.clone());
let poly = domain.lagrange_to_coeff(permutation_poly);
polys.push(poly.clone());
cosets.push(domain.coeff_to_extended(poly));
let mut cosets = vec![domain.empty_extended(); p.columns.len()];
{
parallelize(&mut cosets, |o, start| {
for (x, coset) in o.iter_mut().enumerate() {
let i = start + x;
let poly = polys[i].clone();
*coset = domain.coeff_to_extended(poly);
}
});
}

ProvingKey {
permutations,
polys,
Expand Down

0 comments on commit b3a8f24

Please sign in to comment.