diff --git a/app/igneum-app/src/prover.rs b/app/igneum-app/src/prover.rs index 69cb4d390..7799e7dfc 100644 --- a/app/igneum-app/src/prover.rs +++ b/app/igneum-app/src/prover.rs @@ -341,6 +341,7 @@ fn loop_forever(shared: Arc, bin_dir: PathBuf) { let mut attempted: HashSet<(String, u32)> = HashSet::new(); let mut attempted_segments: HashSet = HashSet::new(); let mut tools: Option = None; + let ram_mb = crate::detect::total_ram_mb(); let mut last_probe = Instant::now() - Duration::from_secs(600); let mut submitted: Vec<(u64, String, u32, u128)> = Vec::new(); let mut last_verifier_read = Instant::now() - Duration::from_secs(600); @@ -407,6 +408,20 @@ fn loop_forever(shared: Arc, bin_dir: PathBuf) { } } let Some(t) = tools.as_ref() else { continue }; + // consequences review C22 (5 October 2026): the SP1 CPU prover takes 29.5 to 30.5 GB of RSS and about five + // minutes a shard whatever the shard size (PC 1, bench-log "the SP1 CPU prover on PC 1"); on a machine under + // 32 GB it would swap the node out, so the CPU path is refused here, Settings or not, with the reason + if !t.cuda { + if let Some(ram) = ram_mb { + if ram < crate::provedefault::MIN_RAM_MB_WINDOWS { + set(&shared, |p| { + p.status = "off".into(); + p.message = format!("the CPU prover needs 32 GB of RAM (30 GB measured on PC 1); this machine has {} GB, so proving stays off here", (ram + 512) / 1024); + }); + continue; + } + } + } set(&shared, |p| { p.enabled = true; p.available = true; @@ -520,7 +535,7 @@ fn loop_forever(shared: Arc, bin_dir: PathBuf) { if !ok || !fixture.exists() { return Err(format!("exporter: {}", out.lines().rev().find(|l| !l.trim().is_empty()).unwrap_or("failed"))); } - set(&shared, |p| p.message = if t.cuda { "proving on the GPU".into() } else { "proving on the CPU (slow)".into() }); + set(&shared, |p| p.message = if t.cuda { "proving on the GPU".into() } else { "CPU prover: about five minutes a shard, 30 GB of RAM, paid only when no card proves first".into() }); let prover_env = if t.cuda { "cuda" } else { "cpu" }; let (ok, out) = run_tool(&shared, t, &t.host, &[fix_p, "--mode".into(), "compressed".into(), "--shard".into(), w.shard.to_string(), "--prover".into(), payout.clone(), "--out".into(), res_p], &[("SP1_PROVER", prover_env), ("RUST_LOG", "off")], Duration::from_secs(3 * 3600), &dir.join(format!("prove-{}-{}.log", w.number, w.shard))); if !ok || !results.exists() {