Skip to content

Commit 278cd5a

Browse files
committed
add P3 fair comparison
1 parent 62c5cd5 commit 278cd5a

36 files changed

Lines changed: 13775 additions & 202 deletions

Cargo.lock

Lines changed: 381 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,8 @@ debug = true
1919

2020
# For profiling with samply/perf, build with:
2121
# CARGO_PROFILE_RELEASE_DEBUG=1 cargo build --release
22+
23+
# Patched p3-goldilocks to disable NEON packing. Used only by bench_vs_plonky3
24+
# for apples-to-apples scalar comparison against Lambda STARK.
25+
[patch.crates-io]
26+
p3-goldilocks = { path = "bench_vs_plonky3/vendor-p3-goldilocks" }

bench_vs_plonky3/Cargo.toml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,18 @@ p3-symmetric = "0.5.2"
2020
p3-merkle-tree = "0.5.2"
2121
p3-keccak = "0.5.2"
2222
p3-fri = "0.5.2"
23-
p3-uni-stark = "0.5.2"
24-
p3-dft = "0.5.2"
23+
p3-uni-stark = { version = "0.5.2", features = ["parallel"] }
24+
p3-dft = { version = "0.5.2", features = ["parallel"] }
2525

2626
[dev-dependencies]
2727
criterion = { version = "0.4", default-features = false }
2828

2929
[features]
30-
default = []
30+
# Both provers run multi-threaded by default: Plonky3's `Radix2DitParallel` DFT
31+
# uses rayon unconditionally, so Lambda must also enable `parallel` for a fair
32+
# apples-to-apples comparison. Disable with `--no-default-features` to compare
33+
# single-threaded.
34+
default = ["parallel"]
3135
parallel = ["stark/parallel"]
3236

3337
[[bench]]

bench_vs_plonky3/benches/stark_comparison.rs

Lines changed: 117 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,38 @@
1-
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
1+
use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main};
22
use crypto::fiat_shamir::default_transcript::DefaultTranscript;
33
use math::field::element::FieldElement;
44
use math::field::extensions_goldilocks::Degree3GoldilocksExtensionField;
55
use math::field::goldilocks::GoldilocksField;
66
use p3_uni_stark::{prove as p3_prove, verify as p3_verify};
7-
use stark::examples::fibonacci_multi_column::{
8-
FibonacciMultiColumnAIR, compute_trace, create_public_inputs,
9-
};
107
use stark::proof::options::ProofOptions;
118
use stark::prover::{IsStarkProver, Prover};
129
use stark::verifier::{IsStarkVerifier, Verifier};
1310

11+
use bench_vs_plonky3::lambda_fibonacci_pair;
1412
use bench_vs_plonky3::plonky3_config;
1513
use bench_vs_plonky3::plonky3_fibonacci;
1614

1715
type F = GoldilocksField;
1816
type E = Degree3GoldilocksExtensionField;
1917
type FE = FieldElement<F>;
2018

21-
/// Number of independent Fibonacci sequences (Lambda columns).
22-
const NUM_SEQUENCES: usize = 2;
19+
/// Number of independent Fibonacci sequences.
20+
const NUM_SEQUENCES: usize = 16;
2321

24-
/// Lambda trace lengths to benchmark.
25-
/// Plonky3 uses half the rows (2 cols per sequence).
26-
const TRACE_SIZES: &[(usize, &str)] = &[
27-
(1 << 12, "2^12"),
28-
(1 << 14, "2^14"),
29-
(1 << 16, "2^16"),
30-
(1 << 18, "2^18"),
31-
(1 << 20, "2^20"),
32-
];
22+
/// Rows (same for both Lambda and Plonky3 — identical AIR shape).
23+
///
24+
/// 2^18 rows × 2 Fibonacci steps packed per row = 2^19 effective Fibonacci
25+
/// steps per sequence, matching Lambda's original `FibonacciMultiColumnAIR`
26+
/// at 2^19 rows × 1 step/row.
27+
const ROWS: usize = 1 << 18;
28+
const TRACE_LABEL: &str = "fib_pair_16seq_2^18";
3329

34-
/// Lambda benchmark proof options: blowup=4, 30 queries, no grinding.
30+
/// Proof options matching Lambda's `profile_prover.rs`:
31+
/// blowup=4, 100 queries, no grinding — production-like settings.
3532
fn benchmark_proof_options() -> ProofOptions {
3633
ProofOptions {
3734
blowup_factor: 4,
38-
fri_number_of_queries: 30,
35+
fri_number_of_queries: 100,
3936
coset_offset: 3,
4037
grinding_factor: 0,
4138
}
@@ -49,140 +46,135 @@ fn lambda_initial_values() -> Vec<(FE, FE)> {
4946

5047
fn bench_lambda_prove(c: &mut Criterion) {
5148
let mut group = c.benchmark_group("lambda_stark/prove");
49+
group.throughput(Throughput::Elements(
50+
(ROWS * 2 * NUM_SEQUENCES) as u64,
51+
));
5252
let proof_options = benchmark_proof_options();
5353

54-
for &(trace_length, label) in TRACE_SIZES {
55-
group.bench_with_input(
56-
BenchmarkId::new("fibonacci", label),
57-
&trace_length,
58-
|b, &trace_length| {
59-
b.iter_with_setup(
60-
|| {
61-
let initial_values = lambda_initial_values();
62-
let trace = compute_trace::<F, E>(&initial_values, trace_length);
63-
let pub_inputs = create_public_inputs(initial_values);
64-
let air = FibonacciMultiColumnAIR::<F, E>::with_num_columns(
65-
&proof_options,
66-
NUM_SEQUENCES,
67-
);
68-
(trace, pub_inputs, air)
69-
},
70-
|(mut trace, pub_inputs, air)| {
71-
Prover::<F, E, _>::prove(
72-
&air,
73-
&mut trace,
74-
&pub_inputs,
75-
&mut DefaultTranscript::<E>::new(&[]),
76-
)
77-
.unwrap()
78-
},
79-
);
80-
},
81-
);
82-
}
54+
group.bench_with_input(
55+
BenchmarkId::new("fibonacci", TRACE_LABEL),
56+
&ROWS,
57+
|b, &rows| {
58+
b.iter_with_setup(
59+
|| {
60+
let initial_values = lambda_initial_values();
61+
let trace = lambda_fibonacci_pair::compute_trace::<F, E>(
62+
&initial_values,
63+
rows,
64+
);
65+
let pub_inputs =
66+
lambda_fibonacci_pair::create_public_inputs(initial_values);
67+
let air = lambda_fibonacci_pair::FibonacciPairMultiColAIR::<F, E>::with_num_sequences(
68+
&proof_options,
69+
NUM_SEQUENCES,
70+
);
71+
(trace, pub_inputs, air)
72+
},
73+
|(mut trace, pub_inputs, air)| {
74+
Prover::<F, E, _>::prove(
75+
&air,
76+
&mut trace,
77+
&pub_inputs,
78+
&mut DefaultTranscript::<E>::new(&[]),
79+
)
80+
.unwrap()
81+
},
82+
);
83+
},
84+
);
8385
group.finish();
8486
}
8587

8688
fn bench_plonky3_prove(c: &mut Criterion) {
8789
let mut group = c.benchmark_group("plonky3_stark/prove");
88-
89-
for &(trace_length, label) in TRACE_SIZES {
90-
// Plonky3 uses half the rows (2 cols per sequence vs Lambda's 1)
91-
let p3_rows = trace_length / 2;
92-
93-
group.bench_with_input(
94-
BenchmarkId::new("fibonacci", label),
95-
&p3_rows,
96-
|b, &p3_rows| {
97-
b.iter_with_setup(
98-
|| {
99-
let config = plonky3_config::matched_params_config();
100-
let air = plonky3_fibonacci::P3FibonacciAir {
101-
num_sequences: NUM_SEQUENCES,
102-
};
103-
let trace =
104-
plonky3_fibonacci::generate_fibonacci_trace(NUM_SEQUENCES, p3_rows);
105-
(config, air, trace)
106-
},
107-
|(config, air, trace)| p3_prove(&config, &air, trace, &[]),
108-
);
109-
},
110-
);
111-
}
90+
group.throughput(Throughput::Elements(
91+
(ROWS * 2 * NUM_SEQUENCES) as u64,
92+
));
93+
94+
group.bench_with_input(
95+
BenchmarkId::new("fibonacci", TRACE_LABEL),
96+
&ROWS,
97+
|b, &rows| {
98+
b.iter_with_setup(
99+
|| {
100+
let config = plonky3_config::matched_params_config();
101+
let air = plonky3_fibonacci::P3FibonacciAir {
102+
num_sequences: NUM_SEQUENCES,
103+
};
104+
let trace =
105+
plonky3_fibonacci::generate_fibonacci_trace(NUM_SEQUENCES, rows);
106+
let pis = plonky3_fibonacci::public_values(NUM_SEQUENCES);
107+
(config, air, trace, pis)
108+
},
109+
|(config, air, trace, pis)| p3_prove(&config, &air, trace, &pis),
110+
);
111+
},
112+
);
112113
group.finish();
113114
}
114115

115116
fn bench_lambda_verify(c: &mut Criterion) {
116117
let mut group = c.benchmark_group("lambda_stark/verify");
118+
group.throughput(Throughput::Elements(
119+
(ROWS * 2 * NUM_SEQUENCES) as u64,
120+
));
117121
let proof_options = benchmark_proof_options();
118122

119-
for &(trace_length, label) in TRACE_SIZES {
120-
// Pre-generate proof
121-
let initial_values = lambda_initial_values();
122-
let mut trace = compute_trace::<F, E>(&initial_values, trace_length);
123-
let pub_inputs = create_public_inputs(initial_values);
124-
let air = FibonacciMultiColumnAIR::<F, E>::with_num_columns(
125-
&proof_options,
126-
NUM_SEQUENCES,
127-
);
128-
let proof = Prover::<F, E, _>::prove(
129-
&air,
130-
&mut trace,
131-
&pub_inputs,
132-
&mut DefaultTranscript::<E>::new(&[]),
133-
)
134-
.unwrap();
135-
136-
group.bench_with_input(
137-
BenchmarkId::new("fibonacci", label),
138-
&trace_length,
139-
|b, _| {
140-
b.iter(|| {
141-
assert!(Verifier::<F, E, _>::verify(
142-
&proof,
143-
&air,
144-
&mut DefaultTranscript::<E>::new(&[]),
145-
))
146-
});
147-
},
148-
);
149-
}
123+
let initial_values = lambda_initial_values();
124+
let mut trace = lambda_fibonacci_pair::compute_trace::<F, E>(&initial_values, ROWS);
125+
let pub_inputs = lambda_fibonacci_pair::create_public_inputs(initial_values);
126+
let air = lambda_fibonacci_pair::FibonacciPairMultiColAIR::<F, E>::with_num_sequences(
127+
&proof_options,
128+
NUM_SEQUENCES,
129+
);
130+
let proof = Prover::<F, E, _>::prove(
131+
&air,
132+
&mut trace,
133+
&pub_inputs,
134+
&mut DefaultTranscript::<E>::new(&[]),
135+
)
136+
.unwrap();
137+
138+
group.bench_with_input(BenchmarkId::new("fibonacci", TRACE_LABEL), &ROWS, |b, _| {
139+
b.iter(|| {
140+
assert!(Verifier::<F, E, _>::verify(
141+
&proof,
142+
&air,
143+
&mut DefaultTranscript::<E>::new(&[]),
144+
))
145+
});
146+
});
150147
group.finish();
151148
}
152149

153150
fn bench_plonky3_verify(c: &mut Criterion) {
154151
let mut group = c.benchmark_group("plonky3_stark/verify");
155-
156-
for &(trace_length, label) in TRACE_SIZES {
157-
let p3_rows = trace_length / 2;
158-
159-
// Pre-generate proof
160-
let air = plonky3_fibonacci::P3FibonacciAir {
161-
num_sequences: NUM_SEQUENCES,
162-
};
163-
let trace = plonky3_fibonacci::generate_fibonacci_trace(NUM_SEQUENCES, p3_rows);
164-
let config = plonky3_config::matched_params_config();
165-
let proof = p3_prove(&config, &air, trace, &[]);
166-
167-
group.bench_with_input(
168-
BenchmarkId::new("fibonacci", label),
169-
&p3_rows,
170-
|b, _| {
171-
b.iter(|| {
172-
let config = plonky3_config::matched_params_config();
173-
p3_verify(&config, &air, &proof, &[]).unwrap();
174-
});
175-
},
176-
);
177-
}
152+
group.throughput(Throughput::Elements(
153+
(ROWS * 2 * NUM_SEQUENCES) as u64,
154+
));
155+
156+
let air = plonky3_fibonacci::P3FibonacciAir {
157+
num_sequences: NUM_SEQUENCES,
158+
};
159+
let trace = plonky3_fibonacci::generate_fibonacci_trace(NUM_SEQUENCES, ROWS);
160+
let pis = plonky3_fibonacci::public_values(NUM_SEQUENCES);
161+
let config = plonky3_config::matched_params_config();
162+
let proof = p3_prove(&config, &air, trace, &pis);
163+
164+
group.bench_with_input(BenchmarkId::new("fibonacci", TRACE_LABEL), &ROWS, |b, _| {
165+
b.iter(|| {
166+
let config = plonky3_config::matched_params_config();
167+
p3_verify(&config, &air, &proof, &pis).unwrap();
168+
});
169+
});
178170
group.finish();
179171
}
180172

181173
criterion_group! {
182174
name = prove_comparison;
183175
config = Criterion::default()
184176
.sample_size(10)
185-
.measurement_time(std::time::Duration::from_secs(60));
177+
.measurement_time(std::time::Duration::from_secs(120));
186178
targets = bench_lambda_prove, bench_plonky3_prove
187179
}
188180

0 commit comments

Comments
 (0)