Skip to content
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

Feat/batched grand products #481

Merged
merged 51 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
6285872
temp
moodlezoup Sep 30, 2024
3f47874
Passes prover assertions
moodlezoup Oct 2, 2024
a607325
temp2
moodlezoup Oct 4, 2024
073bf0d
temp3
moodlezoup Oct 4, 2024
3a4b71a
Sparse layers working(?)
moodlezoup Oct 4, 2024
7dc7baa
temp
moodlezoup Oct 7, 2024
a33f40d
temp
moodlezoup Oct 8, 2024
a6f3276
Fix timestamp range check opening points
moodlezoup Oct 8, 2024
8318fda
temp
moodlezoup Oct 9, 2024
aa6164f
Tests passing
moodlezoup Oct 10, 2024
fa66920
Update profiling command
moodlezoup Oct 10, 2024
2f29e38
Optimize init_final_leaves computation
moodlezoup Oct 10, 2024
0ddcfdb
Add SplitEqPolynomial
moodlezoup Oct 10, 2024
66f84a2
Integrate SplitEqPolynomial into dense grand product
moodlezoup Oct 11, 2024
682af49
SparseInterleavedPolynomial
moodlezoup Oct 15, 2024
16687da
Integrate SparseInterleavedPolynomial into sparse grand product
moodlezoup Oct 15, 2024
1c5059d
temp: par_blocks
moodlezoup Oct 15, 2024
b81e780
Replace bind with bind_par_blocks
moodlezoup Oct 16, 2024
49b30a5
too slow :(
moodlezoup Oct 17, 2024
61fb618
Revert to paralellizing over batch in SparseInterleavedPoly
moodlezoup Oct 22, 2024
7365c72
temp
moodlezoup Oct 22, 2024
227385f
temp2
moodlezoup Oct 23, 2024
f150340
temp
moodlezoup Oct 24, 2024
0d9da3a
Use DenseInterlaevedPolynomial in dense grand product
moodlezoup Oct 24, 2024
30e96df
Fix dense tests
moodlezoup Oct 25, 2024
e0fd5e2
Add dense polynomial benchmarks
moodlezoup Oct 25, 2024
e5ac2fb
switch to scratch space approach
moodlezoup Oct 25, 2024
624f2ac
Use DenseInterleavedPolynomial for coalesced SparseInterleavedPolynomial
moodlezoup Oct 25, 2024
418c95a
temp
moodlezoup Oct 25, 2024
d8a2eff
Refactor (move BatchedCubicSumcheck impls into dense_interleaved_poly…
moodlezoup Oct 25, 2024
adeaaeb
Fix SparseInterleavedPolynomial::layer_output and add debugging
moodlezoup Oct 25, 2024
1357573
temp
moodlezoup Oct 28, 2024
594ee22
tests passing thank god
moodlezoup Oct 28, 2024
c406f83
cleanup
moodlezoup Oct 28, 2024
aa326e1
compute_cubic bench
moodlezoup Oct 29, 2024
75c05db
Switch summation order in DenesInterleavedPolynomial::compute_cubic
moodlezoup Oct 29, 2024
6d1c170
Avoid recomputing E1_evals
moodlezoup Oct 29, 2024
cfa12a2
Switch summation order in SparseInterleavedPolynomial::compute_cubic
moodlezoup Oct 29, 2024
9fce7bc
Fix SparseInterleavedPolynomial::compute_cubic bench
moodlezoup Oct 29, 2024
4f2d125
Drop bound polynomials in background (in primary sumcheck)
moodlezoup Oct 30, 2024
c7a1f0b
Switch summation order in BatchedGrandProductToggleLayer::compute_cubic
moodlezoup Oct 30, 2024
b6c8c21
Optimize for 1s in SparseInterleavedPolynomial::compute_cubic
moodlezoup Oct 31, 2024
00d3354
cleanup
moodlezoup Oct 31, 2024
e2dfc6d
Use simplified RS fingerprint for timestamp range-checks
moodlezoup Oct 31, 2024
5304720
Un-comment surge.rs
moodlezoup Oct 31, 2024
607bdfb
Update Quarks grand product
moodlezoup Nov 1, 2024
f8281eb
Merge remote-tracking branch 'origin/main' into feat/batched-grand-pr…
moodlezoup Nov 4, 2024
d031c8e
clippy
moodlezoup Nov 4, 2024
2a56596
fix benches
moodlezoup Nov 4, 2024
cdedfd3
Update grand_product_example script and disable test
moodlezoup Nov 4, 2024
2cf107a
Add comments
moodlezoup Nov 7, 2024
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
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Just One Lookup Table.

Jolt is a zkVM (zero-knowledge virtual machine) for RISC-V, built to be the simplest, fastest, and most extensible general-purpose of its kind. This repository currently contains an implementation of Jolt for the RISC-V 32-bit Base Integer instruction set (RV32I). _Contributors are welcome!_

The Jolt [paper](https://eprint.iacr.org/2023/1217.pdf) was written by Arasu Arun, Srinath Setty, and Justin Thaler.
The Jolt [paper](https://eprint.iacr.org/2023/1217.pdf) was written by Arasu Arun, Srinath Setty, and Justin Thaler.

## Resources

Expand Down Expand Up @@ -71,15 +71,15 @@ Examples in the [`examples`](./examples/) directory can be run using e.g.

## Performance profiling

Jolt uses [tracing_chrome](https://crates.io/crates/tracing-chrome) for performance profiling.
Jolt uses [tracing_chrome](https://crates.io/crates/tracing-chrome) for performance profiling.

To generate a trace, run:

```cargo run --profile build-fast -p jolt-core trace --name sha3 --format chrome```
```cargo run --release -p jolt-core trace --name sha3 --format chrome --pcs hyper-kzg```

Where `--name` can be `sha2`, `sha3`, `sha2-chain`, or `fibonacci`. The corresponding guest programs can be found in the [`examples`](./examples/) directory. The benchmark inputs are provided in [`bench.rs`](./jolt-core/src/benches/bench.rs).

The above command will output a JSON file, e.g. `trace-1712455107389520.json`, which can be viewed in [Perfetto](https://ui.perfetto.dev/).
The above command will output a JSON file, e.g. `trace-1712455107389520.json`, which can be viewed in [Perfetto](https://ui.perfetto.dev/).

## Acknowledgements

Expand Down
8 changes: 8 additions & 0 deletions jolt-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ harness = false
name = "commit"
harness = false

[[bench]]
name = "binding"
harness = false

[[bench]]
name = "compute_cubic"
harness = false

[lib]
name = "jolt_core"
path = "src/lib.rs"
Expand Down
175 changes: 175 additions & 0 deletions jolt-core/benches/binding.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
use ark_bn254::Fr;
use ark_std::{rand::Rng, test_rng};
use criterion::Criterion;
use jolt_core::field::JoltField;
use jolt_core::poly::dense_interleaved_poly::DenseInterleavedPolynomial;
use jolt_core::poly::dense_mlpoly::DensePolynomial;
use jolt_core::poly::sparse_interleaved_poly::{SparseCoefficient, SparseInterleavedPolynomial};
use jolt_core::subprotocols::sumcheck::Bindable;
use rayon::prelude::*;

fn random_dense_coeffs<F: JoltField>(rng: &mut impl Rng, num_vars: usize) -> Vec<F> {
std::iter::repeat_with(|| F::random(rng))
.take(1 << num_vars)
.collect()
}

fn random_sparse_coeffs<F: JoltField>(
rng: &mut impl Rng,
batch_size: usize,
num_vars: usize,
density: f64,
) -> Vec<Vec<SparseCoefficient<F>>> {
(0..batch_size)
.map(|batch_index| {
let mut coeffs: Vec<SparseCoefficient<F>> = vec![];
for i in 0..(1 << num_vars) {
if rng.gen_bool(density) {
coeffs.push((batch_index * (1 << num_vars) + i, F::random(rng)).into())
}
}
coeffs
})
.collect()
}

fn benchmark_dense<F: JoltField>(c: &mut Criterion, num_vars: usize) {
c.bench_function(
&format!("DensePolynomial::bind {} variables", num_vars),
|b| {
b.iter_with_setup(
|| {
let mut rng = test_rng();
let coeffs = random_dense_coeffs(&mut rng, num_vars);
let poly = DensePolynomial::new(coeffs);
let r: Vec<F> = std::iter::repeat_with(|| F::random(&mut rng))
.take(num_vars)
.collect();
(poly, r)
},
|(mut poly, r)| {
for i in 0..num_vars {
criterion::black_box(poly.bound_poly_var_top_par(&r[i]));
}
},
);
},
);
}

fn benchmark_dense_batch<F: JoltField>(c: &mut Criterion, num_vars: usize, batch_size: usize) {
c.bench_function(
&format!(
"DensePolynomial::bind {} x {} variables",
batch_size, num_vars
),
|b| {
b.iter_with_setup(
|| {
let mut rng = test_rng();
let mut polys = vec![];
for _ in 0..batch_size {
let coeffs = random_dense_coeffs(&mut rng, num_vars);
polys.push(DensePolynomial::new(coeffs));
}
let r: Vec<F> = std::iter::repeat_with(|| F::random(&mut rng))
.take(num_vars)
.collect();
(polys, r)
},
|(mut polys, r)| {
for i in 0..num_vars {
polys
.par_iter_mut()
.for_each(|poly| poly.bound_poly_var_bot(&r[i]))
}
},
);
},
);
}

fn benchmark_dense_interleaved<F: JoltField>(c: &mut Criterion, num_vars: usize) {
c.bench_function(
&format!("DenseInterleavedPolynomial::bind {} variables", num_vars),
|b| {
b.iter_with_setup(
|| {
let mut rng = test_rng();
let coeffs = random_dense_coeffs(&mut rng, num_vars);
let poly = DenseInterleavedPolynomial::new(coeffs);
let r: Vec<F> = std::iter::repeat_with(|| F::random(&mut rng))
.take(num_vars)
.collect();
(poly, r)
},
|(mut poly, r)| {
for i in 0..num_vars {
criterion::black_box(poly.bind(r[i]));
}
},
);
},
);
}

fn benchmark_sparse_interleaved<F: JoltField>(
c: &mut Criterion,
batch_size: usize,
num_vars: usize,
density: f64,
) {
c.bench_function(
&format!(
"SparseInterleavedPolynomial::bind {} x {} variables, {}% ones",
batch_size,
num_vars,
(1.0 - density) * 100.0
),
|b| {
b.iter_with_setup(
|| {
let mut rng = test_rng();
let coeffs = random_sparse_coeffs(&mut rng, batch_size, num_vars, density);
let poly = SparseInterleavedPolynomial::new(coeffs, batch_size << num_vars);
let r: Vec<F> = std::iter::repeat_with(|| F::random(&mut rng))
.take(num_vars)
.collect();
(poly, r)
},
|(mut poly, r)| {
for i in 0..num_vars {
criterion::black_box(poly.bind(r[i]));
}
},
);
},
);
}

fn main() {
let mut criterion = Criterion::default()
.configure_from_args()
.warm_up_time(std::time::Duration::from_secs(5));

benchmark_sparse_interleaved::<Fr>(&mut criterion, 64, 20, 0.1);
benchmark_sparse_interleaved::<Fr>(&mut criterion, 128, 20, 0.1);
benchmark_sparse_interleaved::<Fr>(&mut criterion, 64, 21, 0.1);
benchmark_sparse_interleaved::<Fr>(&mut criterion, 128, 21, 0.1);

// benchmark_dense::<Fr>(&mut criterion, 20);
// benchmark_dense::<Fr>(&mut criterion, 22);
// benchmark_dense::<Fr>(&mut criterion, 24);

// benchmark_dense_interleaved::<Fr>(&mut criterion, 22);
// benchmark_dense_interleaved::<Fr>(&mut criterion, 23);
// benchmark_dense_interleaved::<Fr>(&mut criterion, 24);
// benchmark_dense_interleaved::<Fr>(&mut criterion, 25);

// benchmark_dense_batch::<Fr>(&mut criterion, 20, 4);
// benchmark_dense_batch::<Fr>(&mut criterion, 20, 8);
// benchmark_dense_batch::<Fr>(&mut criterion, 20, 16);
// benchmark_dense_batch::<Fr>(&mut criterion, 20, 32);

criterion.final_summary();
}
126 changes: 126 additions & 0 deletions jolt-core/benches/compute_cubic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
use ark_bn254::Fr;
use ark_std::{rand::Rng, test_rng};
use criterion::Criterion;
use jolt_core::field::JoltField;
use jolt_core::poly::dense_interleaved_poly::DenseInterleavedPolynomial;
use jolt_core::poly::dense_mlpoly::DensePolynomial;
use jolt_core::poly::sparse_interleaved_poly::{SparseCoefficient, SparseInterleavedPolynomial};
use jolt_core::poly::split_eq_poly::SplitEqPolynomial;
use jolt_core::subprotocols::sumcheck::{BatchedCubicSumcheck, Bindable};
use jolt_core::utils::math::Math;
use jolt_core::utils::transcript::KeccakTranscript;
use rayon::prelude::*;

fn random_dense_coeffs<F: JoltField>(rng: &mut impl Rng, num_vars: usize) -> Vec<F> {
std::iter::repeat_with(|| F::random(rng))
.take(1 << num_vars)
.collect()
}

fn random_sparse_coeffs<F: JoltField>(
rng: &mut impl Rng,
batch_size: usize,
num_vars: usize,
density: f64,
) -> Vec<Vec<SparseCoefficient<F>>> {
(0..batch_size)
.map(|batch_index| {
let mut coeffs: Vec<SparseCoefficient<F>> = vec![];
for i in 0..(1 << num_vars) {
if rng.gen_bool(density) {
coeffs.push((batch_index * (1 << num_vars) + i, F::random(rng)).into())
}
}
coeffs
})
.collect()
}

fn benchmark_dense_interleaved<F: JoltField>(c: &mut Criterion, num_vars: usize) {
c.bench_function(
&format!(
"DenseInterleavedPolynomial::compute_cubic {} variables",
num_vars
),
|b| {
b.iter_with_setup(
|| {
let mut rng = test_rng();
let coeffs = random_dense_coeffs(&mut rng, num_vars);
let poly = DenseInterleavedPolynomial::new(coeffs);
let r_eq: Vec<F> = std::iter::repeat_with(|| F::random(&mut rng))
.take(num_vars)
.collect();
let eq_poly = SplitEqPolynomial::new(&r_eq);
let claim = F::random(&mut rng);
(poly, eq_poly, claim)
},
|(poly, eq_poly, claim)| {
criterion::black_box(
BatchedCubicSumcheck::<F, KeccakTranscript>::compute_cubic(
&poly, &eq_poly, claim,
),
);
},
);
},
);
}

fn benchmark_sparse_interleaved<F: JoltField>(
c: &mut Criterion,
batch_size: usize,
num_vars: usize,
density: f64,
) {
c.bench_function(
&format!(
"SparseInterleavedPolynomial::compute_cubic {} x {} variables, {}% ones",
batch_size,
num_vars,
(1.0 - density) * 100.0
),
|b| {
b.iter_with_setup(
|| {
let mut rng = test_rng();
let coeffs = random_sparse_coeffs(&mut rng, batch_size, num_vars, density);
let poly = SparseInterleavedPolynomial::new(coeffs, batch_size << num_vars);
let r_eq: Vec<F> = std::iter::repeat_with(|| F::random(&mut rng))
.take((batch_size << num_vars).next_power_of_two().log_2())
.collect();
let eq_poly = SplitEqPolynomial::new(&r_eq);
let claim = F::random(&mut rng);
(poly, eq_poly, claim)
},
|(poly, eq_poly, claim)| {
criterion::black_box(
BatchedCubicSumcheck::<F, KeccakTranscript>::compute_cubic(
&poly, &eq_poly, claim,
),
);
},
);
},
);
}

fn main() {
let mut criterion = Criterion::default()
.configure_from_args()
.warm_up_time(std::time::Duration::from_secs(5));

// benchmark_dense_interleaved::<Fr>(&mut criterion, 20);
// benchmark_dense_interleaved::<Fr>(&mut criterion, 21);
// benchmark_dense_interleaved::<Fr>(&mut criterion, 22);
// benchmark_dense_interleaved::<Fr>(&mut criterion, 23);
// benchmark_dense_interleaved::<Fr>(&mut criterion, 24);
// benchmark_dense_interleaved::<Fr>(&mut criterion, 25);

benchmark_sparse_interleaved::<Fr>(&mut criterion, 64, 20, 0.1);
benchmark_sparse_interleaved::<Fr>(&mut criterion, 128, 20, 0.1);
benchmark_sparse_interleaved::<Fr>(&mut criterion, 64, 21, 0.1);
benchmark_sparse_interleaved::<Fr>(&mut criterion, 128, 21, 0.1);

criterion.final_summary();
}
Loading
Loading