Skip to content

Commit

Permalink
refactor!: improve internal profiler
Browse files Browse the repository at this point in the history
- Accumulate runtimes, improving profiling accuracy of
  - loops (like in `Stark::verify()`), and
  - repeated runs (like in benchmarks).
- Completely disable profiling in optimized builds. This removes all
  runtime overhead from the performance-critical path. The profiler is
  enabled if
  - `cfg!(debug_assertions)` is true or
  - `--no-default-features` is passed to `cargo`.
- Use a global profiler instance to avoid passing the profiler as an
  explicit argument.
- Combine the `prof_start!` and `prof_stop!` macros into one `profiler!`
  macro.

BREAKING CHANGE: Remove internal profiler from the public API.
  • Loading branch information
jan-ferdinand committed May 13, 2024
2 parents c5b7eec + a76f6ad commit fa7c8b7
Show file tree
Hide file tree
Showing 18 changed files with 818 additions and 756 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ criterion = { version = "0.5", features = ["html_reports"] }
directories = "5"
fs-err = "2.11.0"
get-size = "0.1.4"
indexmap = "2.2.6"
itertools = "0.12"
lazy_static = "1.4"
ndarray = { version = "0.15", features = ["rayon"] }
Expand All @@ -52,6 +53,7 @@ strum = { version = "0.26", features = ["derive"] }
syn = "2.0"
test-strategy = "0.3.1"
thiserror = "1.0"
trybuild = "1.0"
twenty-first = "0.42.0-alpha.2"
unicode-width = "0.1"

Expand Down
6 changes: 6 additions & 0 deletions triton-vm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ arbitrary.workspace = true
colored.workspace = true
criterion.workspace = true
get-size.workspace = true
indexmap.workspace = true
itertools.workspace = true
lazy_static.workspace = true
ndarray.workspace = true
Expand All @@ -48,6 +49,11 @@ proptest.workspace = true
proptest-arbitrary-interop.workspace = true
serde_json.workspace = true
test-strategy.workspace = true
trybuild.workspace = true

[features]
default = ["no_profile"]
no_profile = [] # see `profiler.rs` for an explanation of this seemingly backwards feature

[lints]
workspace = true
Expand Down
4 changes: 2 additions & 2 deletions triton-vm/benches/cached_vs_jit_trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ fn prove_fib<const N: u64>(c: &mut Criterion) {

let mut group = c.benchmark_group(format!("prove_fib_{N}"));
triton_vm::config::overwrite_lde_trace_caching_to(CacheDecision::Cache);
group.bench_function("cache", |b| b.iter(|| stark.prove(&claim, &aet, &mut None)));
group.bench_function("cache", |b| b.iter(|| stark.prove(&claim, &aet)));
triton_vm::config::overwrite_lde_trace_caching_to(CacheDecision::NoCache);
group.bench_function("jit", |b| b.iter(|| stark.prove(&claim, &aet, &mut None)));
group.bench_function("jit", |b| b.iter(|| stark.prove(&claim, &aet)));
group.finish();
}
25 changes: 9 additions & 16 deletions triton-vm/benches/mem_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ use criterion::criterion_main;
use criterion::Criterion;

use triton_vm::prelude::*;
use triton_vm::profiler::Report;
use triton_vm::profiler::TritonProfiler;
use triton_vm::table::master_table::TableId;
use triton_vm::profiler::VMPerformanceProfile;

criterion_main!(benches);
criterion_group!(
Expand All @@ -18,8 +16,8 @@ criterion_group!(

fn mem_io(criterion: &mut Criterion) {
let mem_io = MemIOBench::new();
let report = mem_io.timing_report();
eprintln!("{report}");
let profile = mem_io.performance_profile();
eprintln!("{profile}");

criterion.bench_function("Memory I/O", |b| b.iter(|| mem_io.prove()));
}
Expand Down Expand Up @@ -67,28 +65,23 @@ impl MemIOBench {
triton_vm::prove_program(&self.program, public_input, secret_input).unwrap();
}

fn timing_report(&self) -> Report {
let mut profiler = TritonProfiler::new("Memory I/O");
profiler.start("generate AET", Some("gen".into()));
fn performance_profile(&self) -> VMPerformanceProfile {
let (aet, output) = self
.program
.trace_execution(self.public_input.clone(), self.secret_input.clone())
.unwrap();
profiler.stop("generate AET");

let claim = Claim::about_program(&self.program).with_output(output);

let stark = Stark::default();
let mut profiler = Some(profiler);
let proof = stark.prove(&claim, &aet, &mut profiler).unwrap();
let mut profiler = profiler.unwrap();
triton_vm::profiler::start("Memory I/O");
let proof = stark.prove(&claim, &aet).unwrap();
let profile = triton_vm::profiler::finish();

let trace_len = aet.height_of_table(TableId::OpStack);
let trace_len = aet.height().height;
let padded_height = proof.padded_height().unwrap();
let fri = stark.derive_fri(padded_height).unwrap();

profiler
.report()
profile
.with_cycle_count(trace_len)
.with_padded_height(padded_height)
.with_fri_domain_len(fri.domain.length)
Expand Down
25 changes: 12 additions & 13 deletions triton-vm/benches/prove_fib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ use criterion::Criterion;
use triton_vm::aet::AlgebraicExecutionTrace;
use triton_vm::example_programs::FIBONACCI_SEQUENCE;
use triton_vm::prelude::*;
use triton_vm::profiler::Report;
use triton_vm::profiler::TritonProfiler;
use triton_vm::profiler::VMPerformanceProfile;

const FIBONACCI_INDEX: BFieldElement = BFieldElement::new(100);

Expand All @@ -16,8 +15,8 @@ fn prove_fib(criterion: &mut Criterion) {
let (claim, aet) = trace_execution();
fib_benchmark_group(criterion, &claim, &aet);

let report = prover_timing_report(&claim, &aet);
eprintln!("{report}");
let profile = prover_performance_profile(&claim, &aet);
eprintln!("{profile}");
}

fn fib_benchmark_group(criterion: &mut Criterion, claim: &Claim, aet: &AlgebraicExecutionTrace) {
Expand All @@ -27,23 +26,23 @@ fn fib_benchmark_group(criterion: &mut Criterion, claim: &Claim, aet: &Algebraic
let mut group = criterion.benchmark_group(bench_group_name);

let stark = Stark::default();
group.bench_function(bench_id, |bencher| {
bencher.iter(|| stark.prove(claim, aet, &mut None))
});
group.bench_function(bench_id, |bencher| bencher.iter(|| stark.prove(claim, aet)));
group.finish();
}

fn prover_timing_report(claim: &Claim, aet: &AlgebraicExecutionTrace) -> Report {
fn prover_performance_profile(
claim: &Claim,
aet: &AlgebraicExecutionTrace,
) -> VMPerformanceProfile {
let profile_name = format!("Prove Fibonacci {FIBONACCI_INDEX}");
triton_vm::profiler::start(profile_name);
let stark = Stark::default();
let mut profiler = Some(TritonProfiler::new(profile_name));
let proof = stark.prove(claim, aet, &mut profiler).unwrap();
let mut profiler = profiler.unwrap();
let proof = stark.prove(claim, aet).unwrap();
let profile = triton_vm::profiler::finish();

let padded_height = proof.padded_height().unwrap();
let fri = stark.derive_fri(padded_height).unwrap();
profiler
.report()
profile
.with_cycle_count(aet.processor_trace.nrows())
.with_padded_height(padded_height)
.with_fri_domain_len(fri.domain.length)
Expand Down
51 changes: 23 additions & 28 deletions triton-vm/benches/prove_halt.rs
Original file line number Diff line number Diff line change
@@ -1,49 +1,44 @@
use criterion::criterion_group;
use criterion::criterion_main;
use criterion::BenchmarkId;
use criterion::Criterion;

use triton_vm::profiler::TritonProfiler;
use triton_vm::prelude::NonDeterminism;
use triton_vm::prelude::PublicInput;
use triton_vm::proof::Claim;
use triton_vm::stark::Stark;
use triton_vm::table::master_table::TableId;
use triton_vm::triton_program;

criterion_main!(benches);

criterion_group! {
name = benches;
config = Criterion::default().sample_size(10);
targets = prove_halt
}

/// cargo criterion --bench prove_halt
fn prove_halt(criterion: &mut Criterion) {
fn prove_halt(c: &mut Criterion) {
let program = triton_program!(halt);
let (aet, output) = program.trace_execution([].into(), [].into()).unwrap();
let (aet, output) = program
.trace_execution(PublicInput::default(), NonDeterminism::default())
.unwrap();

let stark = Stark::default();
let claim = Claim::about_program(&program).with_output(output);
let mut profiler = Some(TritonProfiler::new("Prove Halt"));
let proof = stark.prove(&claim, &aet, &mut profiler).unwrap();
let mut profiler = profiler.unwrap();
profiler.finish();
let proof = stark.prove(&claim, &aet).unwrap();

let bench_id = BenchmarkId::new("ProveHalt", 0);
let mut group = criterion.benchmark_group("prove_halt");
group.sample_size(10);
group.bench_function(bench_id, |bencher| {
bencher.iter(|| {
let _proof = stark.prove(&claim, &aet, &mut None);
});
triton_vm::profiler::start("Prove Halt");
c.bench_function("Prove Halt", |b| {
b.iter(|| stark.prove(&claim, &aet).unwrap())
});
group.finish();
let profile = triton_vm::profiler::finish();

let padded_height = proof.padded_height().unwrap();
let fri = stark.derive_fri(padded_height).unwrap();
let report = profiler
.report()
.with_cycle_count(aet.processor_trace.nrows())
let profile = profile
.with_cycle_count(aet.height_of_table(TableId::Processor))
.with_padded_height(padded_height)
.with_fri_domain_len(fri.domain.length);
eprintln!("{report}");
eprintln!("{profile}");
}

criterion_group! {
name = benches;
config = Criterion::default();
targets = prove_halt
}

criterion_main!(benches);
17 changes: 7 additions & 10 deletions triton-vm/benches/verify_halt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use criterion::criterion_main;
use criterion::BenchmarkId;
use criterion::Criterion;

use triton_vm::profiler::TritonProfiler;
use triton_vm::proof::Claim;
use triton_vm::stark::Stark;
use triton_vm::triton_program;
Expand All @@ -16,17 +15,15 @@ fn verify_halt(criterion: &mut Criterion) {
let claim = Claim::about_program(&program);

let (aet, _) = program.trace_execution([].into(), [].into()).unwrap();
let proof = stark.prove(&claim, &aet, &mut None).unwrap();
let proof = stark.prove(&claim, &aet).unwrap();

let mut profiler = Some(TritonProfiler::new("Verify Halt"));
stark.verify(&claim, &proof, &mut profiler).unwrap();
triton_vm::profiler::start("Verify Halt");
stark.verify(&claim, &proof).unwrap();
let profile = triton_vm::profiler::finish();

let mut profiler = profiler.unwrap();
profiler.finish();
let padded_height = proof.padded_height().unwrap();
let fri = stark.derive_fri(padded_height).unwrap();
let report = profiler
.report()
let profile = profile
.with_cycle_count(aet.processor_trace.nrows())
.with_padded_height(padded_height)
.with_fri_domain_len(fri.domain.length);
Expand All @@ -36,12 +33,12 @@ fn verify_halt(criterion: &mut Criterion) {
group.sample_size(10);
group.bench_function(bench_id, |bencher| {
bencher.iter(|| {
let _ = stark.verify(&claim, &proof, &mut None);
let _ = stark.verify(&claim, &proof);
});
});
group.finish();

eprintln!("{report}");
eprintln!("{profile}");
}

criterion_group! {
Expand Down
12 changes: 5 additions & 7 deletions triton-vm/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ mod tests {

use crate::example_programs::FIBONACCI_SEQUENCE;
use crate::prelude::*;
use crate::profiler::TritonProfiler;
use crate::shared_tests::prove_with_low_security_level;

use super::*;
Expand All @@ -94,13 +93,12 @@ mod tests {
let stdin = PublicInput::from(bfe_array![100]);
let secret_in = NonDeterminism::default();

let mut profiler = Some(TritonProfiler::new("Prove Fib 100"));
crate::profiler::start("Prove Fib 100");
let (stark, claim, proof) =
prove_with_low_security_level(&FIBONACCI_SEQUENCE, stdin, secret_in, &mut profiler);
assert!(let Ok(()) = stark.verify(&claim, &proof, &mut None));
prove_with_low_security_level(&FIBONACCI_SEQUENCE, stdin, secret_in);
assert!(let Ok(()) = stark.verify(&claim, &proof));

let mut profiler = profiler.unwrap();
let report = profiler.report();
println!("{report}");
let profile = crate::profiler::finish();
println!("{profile}");
}
}
Loading

0 comments on commit fa7c8b7

Please sign in to comment.