Skip to content

Commit

Permalink
refactor: provide API to overwrite cache decision
Browse files Browse the repository at this point in the history
Allow forcing the LDE trace caching behavior even if setting an
environment variable is infeasible. 

Rename the environment variable to `TVM_LDE_TRACE`, accepting any of the
values `cache` and `no_cache` where capitalization does not matter.

Previously, the decision whether to allocate memory for the low-degree
extended trace table was made ahead of time, and the actual allocation
happened later. Now, the allocation is attempted, and if it does not
succeed, the just-in-time codepath is chosen.

Additionally, performance has improved: `sysinfo`'s function how much
`.free_memory()` is available is apparently prohibitively slow to
execute: ~25ms on a fast system and ~40ms (!) on a standard laptop.
  • Loading branch information
jan-ferdinand committed Apr 30, 2024
1 parent becdc1e commit 0f313a7
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 57 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ serde_derive = "1"
serde_json = "1.0"
strum = { version = "0.26", features = ["derive"] }
syn = "2.0"
sysinfo = "0.30.11"
test-strategy = "0.3.1"
thiserror = "1.0"
twenty-first = "0.40"
Expand Down
1 change: 0 additions & 1 deletion triton-vm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ rayon.workspace = true
serde.workspace = true
serde_derive.workspace = true
strum.workspace = true
sysinfo.workspace = true
thiserror.workspace = true
twenty-first.workspace = true
unicode-width.workspace = true
Expand Down
106 changes: 106 additions & 0 deletions triton-vm/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
use std::cell::RefCell;

use arbitrary::Arbitrary;

thread_local! {
pub(crate) static CONFIG: RefCell<Config> = RefCell::new(Config::default());
}

#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash, Arbitrary)]
pub enum CacheDecision {
#[default]
Cache,
NoCache,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Arbitrary)]
struct Config {
/// Whether to cache the [low-degree extended trace][lde] when [proving].
/// `None` means the decision is made automatically, based on free memory.
/// Can be accessed via [`Config::cache_lde_trace`].
///
/// [lde]: crate::table::master_table::MasterTable::low_degree_extend_all_columns
/// [proving]: crate::stark::Stark::prove
pub cache_lde_trace_overwrite: Option<CacheDecision>,
}

impl Config {
pub fn new() -> Self {
let maybe_overwrite = std::env::var("TVM_LDE_TRACE").map(|s| s.to_ascii_lowercase());
let cache_lde_trace_overwrite = match maybe_overwrite {
Ok(t) if &t == "cache" => Some(CacheDecision::Cache),
Ok(f) if &f == "no_cache" => Some(CacheDecision::NoCache),
_ => None,
};

Self {
cache_lde_trace_overwrite,
}
}
}

impl Default for Config {
fn default() -> Self {
Self::new()
}
}

/// Overwrite the automatic decision whether to cache the [low-degree extended trace][lde] when
/// [proving]. Takes precedence over the environment variable `TVM_LDE_TRACE`.
///
/// Caching the low-degree extended trace improves proving speed but requires more memory. It is
/// generally recommended to cache the trace. Triton VM will make an automatic decision based on
/// free memory. Use this function if you know your requirements better.
///
/// [lde]: crate::table::master_table::MasterTable::low_degree_extend_all_columns
/// [proving]: crate::stark::Stark::prove
pub fn overwrite_lde_trace_caching_to(decision: CacheDecision) {
CONFIG.with_borrow_mut(|config| config.cache_lde_trace_overwrite = Some(decision));
}

/// Should the [low-degree extended trace][lde] be cached? `None` means the
/// decision is made automatically, based on free memory.
///
/// [lde]: crate::table::master_table::MasterTable::low_degree_extend_all_columns
pub(crate) fn cache_lde_trace() -> Option<CacheDecision> {
CONFIG.with_borrow(|config| config.cache_lde_trace_overwrite)
}

#[cfg(test)]
mod tests {
use assert2::assert;
use twenty_first::prelude::*;

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

use super::*;

#[test]
fn triton_vm_can_generate_valid_proof_with_just_in_time_lde() {
overwrite_lde_trace_caching_to(CacheDecision::NoCache);
prove_and_verify_a_triton_vm_program();
}

#[test]
fn triton_vm_can_generate_valid_proof_with_cached_lde_trace() {
overwrite_lde_trace_caching_to(CacheDecision::Cache);
prove_and_verify_a_triton_vm_program();
}

fn prove_and_verify_a_triton_vm_program() {
let stdin = PublicInput::from(bfe_array![100]);
let secret_in = NonDeterminism::default();

let mut profiler = Some(TritonProfiler::new("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));

let mut profiler = profiler.unwrap();
let report = profiler.report();
println!("{report}");
}
}
11 changes: 11 additions & 0 deletions triton-vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
//! For a full overview over all available instructions and their effects, see the
//! [specification](https://triton-vm.org/spec/instructions.html).
//!
//! # Time / Memory Trade-Offs
//!
//! Parts of the [proof generation](Stark::prove) process can trade time for memory. The
//! [config] module provides ways to control these trade-offs. Additionally, and with lower
//! precedence, they can be controlled via the following environment variables:
//!
//! - `TVM_LDE_TRACE`: Set to `cache` to cache the low-degree extended trace. Set to `no_cache`
//! to not cache it. If unset (or set to anything else), Triton VM will make an automatic decision
//! based on free memory.
//!
//! # Examples
//!
//! Convenience function [`prove_program()`] as well as the [`prove()`] and [`verify()`] methods
Expand Down Expand Up @@ -148,6 +158,7 @@ use crate::prelude::*;

pub mod aet;
pub mod arithmetic_domain;
pub mod config;
pub mod error;
pub mod example_programs;
pub mod fri;
Expand Down
3 changes: 3 additions & 0 deletions triton-vm/src/stark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ pub struct Stark {
}

impl Stark {
/// # Panics
///
/// Panics if `log2_of_fri_expansion_factor` is zero.
pub fn new(security_level: usize, log2_of_fri_expansion_factor: usize) -> Self {
assert_ne!(
0, log2_of_fri_expansion_factor,
Expand Down
Loading

0 comments on commit 0f313a7

Please sign in to comment.