diff --git a/tools/attack/adv-accept/src/main.rs b/tools/attack/adv-accept/src/main.rs index 7505e0443..90d14c10f 100644 --- a/tools/attack/adv-accept/src/main.rs +++ b/tools/attack/adv-accept/src/main.rs @@ -634,6 +634,14 @@ fn attempts_cmd(args: &[String]) { let t0 = Instant::now(); let next = AtomicUsize::new(0); let done_n = AtomicUsize::new(0); + // running totals shared across threads so a progress tick (and a pre-emption) leaves a usable record + let tot_rej: Vec = (0..11).map(|_| std::sync::atomic::AtomicU64::new(0)).collect(); + let tot_acc: Vec = (0..=256).map(|_| std::sync::atomic::AtomicU64::new(0)).collect(); + let tot_exh = std::sync::atomic::AtomicU64::new(0); + let outfile = if out.is_empty() { None } else { Some(std::sync::Mutex::new(std::fs::File::create(&out).unwrap())) }; + if let Some(f) = &outfile { + writeln!(f.lock().unwrap(), "# seed accepted_attempt program_id distinct_mean (rows written as they land; a pre-empted run keeps them)").unwrap(); + } // per attempt index (0..=MAX): counts of each reject class; the accepted attempt histogram; exhaustions const CLASSES: usize = 11; fn class_of(r: &Reject) -> usize { @@ -655,7 +663,7 @@ fn attempts_cmd(args: &[String]) { let parts: Vec<(Vec<[u64; CLASSES]>, Vec, u64, Vec, Vec<(u64, u32, u64, f64)>)> = std::thread::scope(|sc| { let mut hs = Vec::new(); for _ in 0..threads { - let (next, done_n) = (&next, &done_n); + let (next, done_n, tot_rej, tot_acc, tot_exh, outfile) = (&next, &done_n, &tot_rej, &tot_acc, &tot_exh, &outfile); hs.push(sc.spawn(move || { let mut by_attempt = vec![[0u64; CLASSES]; MAX_ATTEMPTS_V4 as usize + 1]; let mut accepted_at = vec![0u64; MAX_ATTEMPTS_V4 as usize + 1]; @@ -678,20 +686,27 @@ fn attempts_cmd(args: &[String]) { match check(&p) { Ok(r) if !force_exhaust => { accepted_at[a as usize] += 1; + tot_acc[a as usize].fetch_add(1, Ordering::Relaxed); + if let Some(f) = outfile { + writeln!(f.lock().unwrap(), "{k} {a} {:016x} {:.5}", p.program_id(), r.distinct_mean()).unwrap(); + } rows.push((k, a, p.program_id(), r.distinct_mean())); done = true; break; } Ok(_) => { by_attempt[a as usize][3] += 0; } // forced: counted as a rejection of no class - Err(r) => { by_attempt[a as usize][class_of(&r)] += 1; } + Err(r) => { by_attempt[a as usize][class_of(&r)] += 1; tot_rej[class_of(&r)].fetch_add(1, Ordering::Relaxed); } } } let d = done_n.fetch_add(1, Ordering::Relaxed) + 1; if d % 500 == 0 { - println!("progress: {d} of {seeds} seeds in {:.0} s", t0.elapsed().as_secs_f64()); + let rej: Vec = tot_rej.iter().map(|x| x.load(Ordering::Relaxed)).collect(); + let acc: Vec = tot_acc.iter().take(12).map(|x| x.load(Ordering::Relaxed)).collect(); + println!("progress: {d} of {seeds} seeds in {:.0} s; running rejections by part {}; accepted-attempt 0..11 {:?}; exhausted {}", t0.elapsed().as_secs_f64(), NAMES.iter().zip(rej.iter()).map(|(n, c)| format!("{n}={c}")).collect::>().join(" "), acc, tot_exh.load(Ordering::Relaxed)); } if !done { exhausted += 1; + tot_exh.fetch_add(1, Ordering::Relaxed); let mut lr = candidate_class(&label, &epoch, cap, class); lr.generator = GENERATOR_VERSION_V4; let lr = last_resort_v4(lr); @@ -734,10 +749,7 @@ fn attempts_cmd(args: &[String]) { println!("closed-form distinct-item mean of accepted programs: mean {:.4} min {:.4}", dm.iter().sum::() / dm.len() as f64, dm.iter().cloned().fold(f64::MAX, f64::min)); } if !out.is_empty() { - let mut f = std::fs::File::create(&out).unwrap(); - writeln!(f, "# seed accepted_attempt program_id distinct_mean").unwrap(); - for (k, a, id, d) in &rows { writeln!(f, "{k} {a} {id:016x} {d:.5}").unwrap(); } - println!("wrote {out}"); + println!("rows were written to {out} as they landed ({} rows)", rows.len()); } println!("attempts DONE"); }