Skip to content

Commit 1018e6b

Browse files
feat(sdk): async app prover (#2154)
Adds `AsyncAppProver` which executes metered serially and then re-executes while spawning prover tasks for each continuation segment. The prover tasks use a semaphore to limit the max concurrency. Note this PR includes the fix #2155 --------- Co-authored-by: Ayush Shukla <[email protected]>
1 parent 4dd8d15 commit 1018e6b

File tree

8 files changed

+285
-70
lines changed

8 files changed

+285
-70
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,11 @@ lto = "thin"
113113

114114
[workspace.dependencies]
115115
# Stark Backend
116-
openvm-stark-backend = { git = "https://github.com/openvm-org/stark-backend.git", branch="fix/async-errors", default-features = false }
117-
openvm-stark-sdk = { git = "https://github.com/openvm-org/stark-backend.git", branch="fix/async-errors", default-features = false }
118-
openvm-cuda-backend = { git = "https://github.com/openvm-org/stark-backend.git", branch="fix/async-errors", default-features = false }
119-
openvm-cuda-builder = { git = "https://github.com/openvm-org/stark-backend.git", branch="fix/async-errors", default-features = false }
120-
openvm-cuda-common = { git = "https://github.com/openvm-org/stark-backend.git", branch="fix/async-errors", default-features = false }
116+
openvm-stark-backend = { git = "https://github.com/openvm-org/stark-backend.git", branch="main", default-features = false }
117+
openvm-stark-sdk = { git = "https://github.com/openvm-org/stark-backend.git", branch="main", default-features = false }
118+
openvm-cuda-backend = { git = "https://github.com/openvm-org/stark-backend.git", branch="main", default-features = false }
119+
openvm-cuda-builder = { git = "https://github.com/openvm-org/stark-backend.git", branch="main", default-features = false }
120+
openvm-cuda-common = { git = "https://github.com/openvm-org/stark-backend.git", branch="main", default-features = false }
121121

122122
# OpenVM
123123
openvm-sdk = { path = "crates/sdk", default-features = false }
@@ -233,6 +233,7 @@ dashmap = "6.1.0"
233233
memmap2 = "0.9.5"
234234
libc = "0.2.175"
235235
tracing-subscriber = { version = "0.3.20", features = ["std", "env-filter"] }
236+
tokio = "1" # >=1.0.0 to allow downstream flexibility
236237

237238
# default-features = false for no_std for use in guest programs
238239
itertools = { version = "0.14.0", default-features = false }

benchmarks/prove/Cargo.toml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ openvm-native-circuit.workspace = true
1919
openvm-native-compiler.workspace = true
2020
openvm-native-recursion = { workspace = true, features = ["test-utils"] }
2121

22-
clap = { version = "4.5.9", features = ["derive", "env"] }
22+
clap = { workspace = true, features = ["derive", "env"] }
2323
eyre.workspace = true
24-
tokio = { version = "1.43.1", features = ["rt", "rt-multi-thread", "macros", "time"] }
24+
tokio = { workspace = true, features = ["rt", "rt-multi-thread", "macros"] }
2525
rand_chacha = { version = "0.3", default-features = false }
2626
k256 = { workspace = true, features = ["ecdsa"] }
2727
tiny-keccak.workspace = true
@@ -33,11 +33,12 @@ metrics.workspace = true
3333
[dev-dependencies]
3434

3535
[features]
36-
default = ["parallel", "jemalloc", "metrics"]
36+
default = ["parallel", "jemalloc", "metrics", "async"]
3737
metrics = ["openvm-sdk/metrics"]
3838
tco = ["openvm-sdk/tco"]
3939
perf-metrics = ["openvm-sdk/perf-metrics", "metrics"]
4040
stark-debug = ["openvm-sdk/stark-debug"]
41+
async = ["openvm-sdk/async"]
4142
# runs leaf aggregation benchmarks:
4243
aggregation = []
4344
evm = ["openvm-sdk/evm-verify"]
@@ -63,3 +64,8 @@ path = "src/bin/fib_e2e.rs"
6364
[[bin]]
6465
name = "kitchen_sink"
6566
path = "src/bin/kitchen_sink.rs"
67+
68+
[[bin]]
69+
name = "async_regex"
70+
path = "src/bin/async_regex.rs"
71+
required-features = ["async"]
Lines changed: 10 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,14 @@
1-
use std::{
2-
env::var,
3-
sync::{
4-
atomic::{AtomicUsize, Ordering},
5-
Arc,
6-
},
7-
time::Duration,
8-
};
1+
use std::env::var;
92

103
use clap::Parser;
114
use openvm_benchmarks_prove::util::BenchmarkCli;
125
use openvm_benchmarks_utils::get_programs_dir;
136
use openvm_sdk::{
147
config::{SdkVmBuilder, SdkVmConfig},
15-
prover::AppProver,
8+
prover::AsyncAppProver,
169
DefaultStarkEngine, Sdk, StdIn, F,
1710
};
1811
use openvm_stark_sdk::config::setup_tracing;
19-
use tokio::{spawn, task::spawn_blocking, time::sleep};
2012

2113
#[tokio::main]
2214
async fn main() -> eyre::Result<()> {
@@ -47,46 +39,15 @@ async fn main() -> eyre::Result<()> {
4739
let (app_pk, _app_vk) = sdk.app_keygen();
4840

4941
let max_par_jobs: usize = var("MAX_PAR_JOBS").map(|m| m.parse()).unwrap_or(Ok(1))?;
50-
let num_jobs: usize = var("NUM_JOBS").map(|m| m.parse()).unwrap_or(Ok(20))?;
51-
let cur_num_jobs = Arc::new(AtomicUsize::new(0));
5242

53-
let mut tasks = Vec::with_capacity(num_jobs);
54-
for idx in 0..num_jobs {
55-
let cur_num_jobs = cur_num_jobs.clone();
56-
let app_exe = app_exe.clone();
57-
let app_pk = app_pk.clone();
58-
let input = input.clone();
59-
let task = spawn(async move {
60-
loop {
61-
let c = cur_num_jobs.fetch_add(1, Ordering::SeqCst);
62-
if c < max_par_jobs {
63-
tracing::info!("Acquired job {}, cur num jobs {}", idx, c + 1);
64-
break;
65-
}
66-
cur_num_jobs.fetch_sub(1, Ordering::SeqCst);
67-
sleep(Duration::from_millis(100)).await;
68-
}
69-
let res = spawn_blocking(move || -> eyre::Result<()> {
70-
let mut prover = AppProver::<DefaultStarkEngine, _>::new(
71-
SdkVmBuilder,
72-
&app_pk.app_vm_pk,
73-
app_exe,
74-
app_pk.leaf_verifier_program_commit(),
75-
)?;
76-
let _proof = prover.prove(input)?;
77-
Ok(())
78-
})
79-
.await?;
80-
let prev_num = cur_num_jobs.fetch_sub(1, Ordering::SeqCst);
81-
tracing::info!("Decrement cur_num_jobs {} to {}", prev_num, prev_num - 1);
82-
res
83-
});
84-
tasks.push(task);
85-
sleep(Duration::from_millis(1000)).await;
86-
}
87-
for task in tasks {
88-
task.await??;
89-
}
43+
let prover = AsyncAppProver::<DefaultStarkEngine, _>::new(
44+
SdkVmBuilder,
45+
app_pk.app_vm_pk.clone(),
46+
app_exe,
47+
app_pk.leaf_verifier_program_commit(),
48+
max_par_jobs,
49+
)?;
50+
let _proof = prover.prove(input).await?;
9051

9152
Ok(())
9253
}

crates/sdk/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,10 @@ forge-fmt = { workspace = true, optional = true }
6161
rrs-lib.workspace = true
6262
num-bigint.workspace = true
6363
cfg-if.workspace = true
64+
tokio = { workspace = true, features = ["rt", "sync"], optional = true }
6465

6566
[features]
66-
default = ["parallel", "jemalloc"]
67+
default = ["parallel", "jemalloc", "async"]
6768
evm-prove = [
6869
"openvm-continuations/static-verifier",
6970
"openvm-native-recursion/evm-prove",
@@ -101,6 +102,7 @@ perf-metrics = [
101102
# turns on stark-backend debugger in all proofs
102103
stark-debug = ["openvm-circuit/stark-debug"]
103104
test-utils = ["openvm-circuit/test-utils"]
105+
async = ["tokio"]
104106
# performance features:
105107
# (rayon is always imported because of halo2, so "parallel" feature is redundant)
106108
parallel = ["openvm-circuit/parallel"]

0 commit comments

Comments
 (0)