Some arithm optims

This commit is contained in:
wborgeaud 2021-08-13 10:40:31 +02:00
parent bbfc0f8adc
commit 21669be246
7 changed files with 83 additions and 26 deletions

View File

@ -139,7 +139,13 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let precomputed_reduced_evals = with_context!(
self,
"precompute reduced evaluations",
PrecomputedReducedEvalsTarget::from_os_and_alpha(os, alpha, self)
PrecomputedReducedEvalsTarget::from_os_and_alpha(
os,
alpha,
common_data.degree_bits,
zeta,
self
)
);
for (i, round_proof) in proof.query_round_proofs.iter().enumerate() {
@ -209,6 +215,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
precomputed_reduced_evals: PrecomputedReducedEvalsTarget<D>,
common_data: &CommonCircuitData<F, D>,
) -> ExtensionTarget<D> {
println!("combine initial: {}", self.num_gates());
assert!(D > 1, "Not implemented for D=1.");
let config = self.config.clone();
let degree_log = common_data.degree_bits;
@ -246,6 +253,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
sum = self.div_add_extension(single_numerator, vanish_zeta, sum);
alpha.reset();
println!("done single: {}", self.num_gates());
// Polynomials opened at `x` and `g x`, i.e., the Zs polynomials.
let zs_evals = proof
.unsalted_evals(PlonkPolynomials::ZS_PARTIAL_PRODUCTS, config.zero_knowledge)
@ -255,20 +263,21 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
.collect::<Vec<_>>();
let zs_composition_eval = alpha.reduce_base(&zs_evals, self);
let g = self.constant_extension(F::Extension::primitive_root_of_unity(degree_log));
let zeta_right = self.mul_extension(g, zeta);
let interpol_val = self.interpolate2(
[
(zeta, precomputed_reduced_evals.zs),
(zeta_right, precomputed_reduced_evals.zs_right),
],
subgroup_x,
let interpol_val = self.mul_add_extension(
vanish_zeta,
precomputed_reduced_evals.slope,
precomputed_reduced_evals.zs,
);
let (zs_numerator, vanish_zeta_right) =
self.sub_two_extension(zs_composition_eval, interpol_val, subgroup_x, zeta_right);
let zs_denominator = self.mul_extension(vanish_zeta, vanish_zeta_right);
sum = alpha.shift(sum, self);
let (zs_numerator, vanish_zeta_right) = self.sub_two_extension(
zs_composition_eval,
interpol_val,
subgroup_x,
precomputed_reduced_evals.zeta_right,
);
let (mut sum, zs_denominator) =
alpha.shift_and_mul(sum, vanish_zeta, vanish_zeta_right, self);
sum = self.div_add_extension(zs_numerator, zs_denominator, sum);
println!("done doubles: {}", self.num_gates());
sum
}
@ -286,6 +295,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
round_proof: &FriQueryRoundTarget<D>,
common_data: &CommonCircuitData<F, D>,
) {
println!("query round: {}", self.num_gates());
let config = &common_data.config.fri_config;
let n_log = log2_strict(n);
// TODO: Do we need to range check `x_index` to a target smaller than `p`?
@ -308,7 +318,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
// `subgroup_x` is `subgroup[x_index]`, i.e., the actual field element in the domain.
let mut subgroup_x = with_context!(self, "compute x from its index", {
let g = self.constant(F::MULTIPLICATIVE_GROUP_GENERATOR);
let g = self.constant(F::coset_shift());
let phi = self.constant(F::primitive_root_of_unity(n_log));
let phi = self.exp_from_bits(phi, x_index_bits.iter().rev());
@ -331,6 +341,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
);
for (i, &arity_bits) in config.reduction_arity_bits.iter().enumerate() {
println!("query round, {}-th arity: {}", i, self.num_gates());
let evals = &round_proof.steps[i].evals;
// Split x_index into the index of the coset x is in, and the index of x within that coset.
@ -393,12 +404,16 @@ struct PrecomputedReducedEvalsTarget<const D: usize> {
pub single: ExtensionTarget<D>,
pub zs: ExtensionTarget<D>,
pub zs_right: ExtensionTarget<D>,
pub slope: ExtensionTarget<D>,
pub zeta_right: ExtensionTarget<D>,
}
impl<const D: usize> PrecomputedReducedEvalsTarget<D> {
fn from_os_and_alpha<F: Extendable<D>>(
os: &OpeningSetTarget<D>,
alpha: ExtensionTarget<D>,
degree_log: usize,
zeta: ExtensionTarget<D>,
builder: &mut CircuitBuilder<F, D>,
) -> Self {
let mut alpha = ReducingFactorTarget::new(alpha);
@ -416,10 +431,16 @@ impl<const D: usize> PrecomputedReducedEvalsTarget<D> {
let zs = alpha.reduce(&os.plonk_zs, builder);
let zs_right = alpha.reduce(&os.plonk_zs_right, builder);
let g = builder.constant_extension(F::Extension::primitive_root_of_unity(degree_log));
let zeta_right = builder.mul_extension(g, zeta);
let (numerator, denominator) = builder.sub_two_extension(zs_right, zs, zeta_right, zeta);
Self {
single,
zs,
zs_right,
slope: builder.div_extension(numerator, denominator),
zeta_right,
}
}
}

View File

@ -12,9 +12,10 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
interpolation_points: [(ExtensionTarget<D>, ExtensionTarget<D>); 2],
evaluation_point: ExtensionTarget<D>,
) -> ExtensionTarget<D> {
// a0 -> a1
// b0 -> b1
// a0 -> a1 : zeta -> precomp0
// b0 -> b1 : g*zeta -> precomp1
// x -> a1 + (x-a0)*(b1-a1)/(b0-a0)
// x -> precomp0 + (x-zeta)*(precomp1-precomp0)/(g*zeta - zeta)
let (x_m_a0, b1_m_a1) = self.sub_two_extension(
evaluation_point,

View File

@ -24,16 +24,16 @@ impl<const D: usize> ArithmeticExtensionGate<D> {
pub fn wires_first_addend() -> Range<usize> {
2 * D..3 * D
}
pub fn wires_second_multiplicand_0() -> Range<usize> {
pub fn wires_first_output() -> Range<usize> {
3 * D..4 * D
}
pub fn wires_second_multiplicand_1() -> Range<usize> {
pub fn wires_second_multiplicand_0() -> Range<usize> {
4 * D..5 * D
}
pub fn wires_second_addend() -> Range<usize> {
pub fn wires_second_multiplicand_1() -> Range<usize> {
5 * D..6 * D
}
pub fn wires_first_output() -> Range<usize> {
pub fn wires_second_addend() -> Range<usize> {
6 * D..7 * D
}
pub fn wires_second_output() -> Range<usize> {

View File

@ -1,6 +1,7 @@
use crate::iop::target::Target;
/// A named copy constraint.
#[derive(Debug)]
pub struct CopyConstraint {
pub pair: (Target, Target),
pub name: String,

View File

@ -68,6 +68,26 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
partial_witness.full_witness(degree, num_wires)
);
{
let mut count = 0;
let mut count_bad = 0;
for i in 0..degree {
if prover_data.gate_instances[i].gate_ref.0.id()
!= "ArithmeticExtensionGate".to_string()
{
continue;
}
count += 1;
let row = witness.wire_values.iter().map(|c| c[i]).collect::<Vec<_>>();
// println!("{} {:?}", i, &row);
if row[16..].iter().all(|x| x.is_zero()) {
println!("{} {:?}", i, row);
count_bad += 1;
}
}
println!("{} {}", count, count_bad);
}
let wires_values: Vec<PolynomialValues<F>> = timed!(
timing,
"compute wire polynomials",

View File

@ -426,7 +426,7 @@ mod tests {
const D: usize = 4;
let config = CircuitConfig {
num_wires: 126,
num_routed_wires: 37,
num_routed_wires: 64,
security_bits: 128,
rate_bits: 3,
num_challenges: 3,
@ -434,7 +434,7 @@ mod tests {
cap_height: 3,
fri_config: FriConfig {
proof_of_work_bits: 1,
reduction_arity_bits: vec![2, 2, 2, 2, 2, 2],
reduction_arity_bits: vec![3, 3, 3],
num_query_rounds: 40,
cap_height: 3,
},
@ -443,9 +443,9 @@ mod tests {
let (proof_with_pis, vd, cd) = {
let mut builder = CircuitBuilder::<F, D>::new(config.clone());
let _two = builder.two();
let _two = builder.hash_n_to_hash(vec![_two], true).elements[0];
let mut _two = builder.hash_n_to_hash(vec![_two], true).elements[0];
for _ in 0..10000 {
let _two = builder.mul(_two, _two);
_two = builder.mul(_two, _two);
}
let data = builder.build();
(

View File

@ -211,9 +211,23 @@ impl<const D: usize> ReducingFactorTarget<D> {
F: Extendable<D>,
{
let exp = builder.exp_u64_extension(self.base, self.count);
let tmp = builder.mul_extension(exp, x);
self.count = 0;
tmp
builder.mul_extension(exp, x)
}
pub fn shift_and_mul<F>(
&mut self,
x: ExtensionTarget<D>,
a: ExtensionTarget<D>,
b: ExtensionTarget<D>,
builder: &mut CircuitBuilder<F, D>,
) -> (ExtensionTarget<D>, ExtensionTarget<D>)
where
F: Extendable<D>,
{
let exp = builder.exp_u64_extension(self.base, self.count);
self.count = 0;
builder.mul_two_extension(exp, x, a, b)
}
pub fn reset(&mut self) {