Skip to content

Reintroduce "Parallelise perm_aggreg" w/ bugfix #3121

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

Merged
merged 2 commits into from
Apr 2, 2025
Merged
Changes from all commits
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
62 changes: 47 additions & 15 deletions kimchi/src/circuits/polynomials/permutation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,6 @@ impl<F: PrimeField, G: KimchiCurve<ScalarField = F>, OpeningProof: OpenProof<G>>

&bnd1.scale(alpha1) + &bnd2.scale(alpha2)
};

Ok((perm, bnd))
}

Expand Down Expand Up @@ -446,8 +445,6 @@ impl<F: PrimeField, G: KimchiCurve<ScalarField = F>, OpeningProof: OpenProof<G>>
//~ The first evaluation represents the initial value of the accumulator:
//~ $$z(g^0) = 1$$

let mut z = vec![F::one(); n];

//~ For $i = 0, \cdot, n - 4$, where $n$ is the size of the domain,
//~ evaluations are computed as:
//~
Expand Down Expand Up @@ -481,27 +478,61 @@ impl<F: PrimeField, G: KimchiCurve<ScalarField = F>, OpeningProof: OpenProof<G>>
//~ \end{align}
//~ $$
//~
for j in 0..n - 1 {
z[j + 1] = witness
.iter()
.zip(self.column_evaluations.permutation_coefficients8.iter())
.map(|(w, s)| w[j] + (s[8 * j] * beta) + gamma)
.fold(F::one(), |x, y| x * y);
}

// We compute z such that:
// z[0] = 1
// z[j+1] = \Prod_{i=0}^{PERMUTS}(wit[i][j] + (s[i][8*j] * beta) + gamma) for j ∈ 0..n-1
//
// We compute every product batch separately first (one batch
// per i∈[COLUMNS]), and then multiply all batches together.
//
// Note that we zip array of COLUMNS with array of PERMUTS;
// Since PERMUTS < COLUMNS, that's what's actually used.
let mut z: Vec<F> = witness
.par_iter()
.zip(self.column_evaluations.permutation_coefficients8.par_iter())
.map(|(w_i, perm_coeffs8_i)| {
Copy link
Contributor

Choose a reason for hiding this comment

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

I would keep the name s instead of perm_coeffs as it is the one in the comment, it’s shorter and it make sense if you know plonk

Copy link
Member Author

Choose a reason for hiding this comment

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

I wanted to rename for clarity, I was confused by s (thought it was shifts), and it's consistent with the general effort to use more self-descriptive variable names...

let mut output_vec: Vec<_> = vec![F::one(); 1];
for (j, w_i_j) in w_i.iter().enumerate().take(n - 1) {
output_vec.push(*w_i_j + (perm_coeffs8_i[8 * j] * beta) + gamma);
}
output_vec
})
.reduce_with(|mut l, r| {
for i in 0..n {
l[i] *= &r[i];
}
l
})
.unwrap();

ark_ff::fields::batch_inversion::<F>(&mut z[1..n]);

let z_prefolded: Vec<F> = witness
.par_iter()
.zip(self.cs.shift.par_iter())
.map(|(w_i, shift_i)| {
let mut output_vec: Vec<_> = vec![F::one(); 1];
for (j, w_i_j) in w_i.iter().enumerate().take(n - 1) {
output_vec.push(*w_i_j + (self.cs.sid[j] * beta * shift_i) + gamma);
}
output_vec
})
.reduce_with(|mut l, r| {
for i in 0..n {
l[i] *= &r[i];
}
l
})
.unwrap();
Comment on lines +511 to +527
Copy link
Contributor

Choose a reason for hiding this comment

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

The code could probably be unified with the code of z.


//~ We randomize the evaluations at `n - zk_rows + 1` and `n - zk_rows + 2` in order to add
//~ zero-knowledge to the protocol.
//~
for j in 0..n - 1 {
if j != n - zk_rows && j != n - zk_rows + 1 {
let x = z[j];
z[j + 1] *= witness
.iter()
.zip(self.cs.shift.iter())
.map(|(w, s)| w[j] + (self.cs.sid[j] * beta * s) + gamma)
.fold(x, |z, y| z * y);
z[j + 1] *= z_prefolded[j + 1] * x;
} else {
z[j + 1] = F::rand(rng);
}
Expand All @@ -514,6 +545,7 @@ impl<F: PrimeField, G: KimchiCurve<ScalarField = F>, OpeningProof: OpenProof<G>>
};

let res = Evaluations::<F, D<F>>::from_vec_and_domain(z, self.cs.domain.d1).interpolate();

Ok(res)
}
}
Loading