fix: start to fix this mess (at least it compiles now)

This commit is contained in:
Christoph J. Scherr 2024-07-22 12:17:11 +02:00
parent 43355d938f
commit f2eb1f57ac
7 changed files with 38 additions and 20 deletions

View File

@ -27,7 +27,7 @@ anyhow = "1.0.81"
chrono = { version = "0.4.37" } chrono = { version = "0.4.37" }
clap = { version = "4.5.3", features = ["derive"], optional = true } clap = { version = "4.5.3", features = ["derive"], optional = true }
colored = { version = "2.1.0", optional = false } colored = { version = "2.1.0", optional = false }
libpt = "0.4.2" libpt = "0.6.0"
num_cpus = "1.16.0" num_cpus = "1.16.0"
rand = "0.8.5" rand = "0.8.5"
rayon = "1.10.0" rayon = "1.10.0"

View File

@ -17,7 +17,7 @@ pub struct BuiltinBenchmark<'wl, WL: WordList, SL: Solver<'wl, WL>> {
builder: GameBuilder<'wl, WL>, builder: GameBuilder<'wl, WL>,
report: Arc<RwLock<Report>>, report: Arc<RwLock<Report>>,
finished: AtomicBool, finished: AtomicBool,
bench_th: Arc<Mutex<Option<JoinHandle<WResult<Report>>>>> // HACK: this is unholy bench_th: Arc<Mutex<Option<JoinHandle<WResult<Report>>>>>, // HACK: this is unholy
} }
impl<'wl, WL, SL> Benchmark<'wl, WL, SL> for BuiltinBenchmark<'wl, WL, SL> impl<'wl, WL, SL> Benchmark<'wl, WL, SL> for BuiltinBenchmark<'wl, WL, SL>
@ -40,7 +40,7 @@ where
report: Arc::new(RwLock::new(Report::new(builder.build()?))), report: Arc::new(RwLock::new(Report::new(builder.build()?))),
builder, builder,
finished: AtomicBool::new(false), finished: AtomicBool::new(false),
bench_th: Arc::new(Mutex::new(None)) bench_th: Arc::new(Mutex::new(None)),
}) })
} }
#[inline] #[inline]
@ -72,14 +72,11 @@ where
fn is_finished(&self) -> bool { fn is_finished(&self) -> bool {
self.finished.load(std::sync::atomic::Ordering::Relaxed) self.finished.load(std::sync::atomic::Ordering::Relaxed)
} }
fn start(&'wl self, n: usize) -> WResult<()> { fn start(&'wl self, n: usize, builder: &'wl GameBuilder<'wl, WL>) -> WResult<()> {
let report = self.report_shared(); let report = self.report_shared();
let solver = self.solver(); let solver = self.solver();
let builder = self.builder(); // TODO: make this run in another thread somehow
let th = std::thread::spawn(move||{ Self::bench(n, report, solver, &builder);
Self::bench(n, report, solver, builder)
});
*self.bench_th.lock().expect("lock is poisoned") = Some(th);
Ok(()) Ok(())
} }
} }

View File

@ -44,14 +44,18 @@ where
// TODO: add some interface to get reports while the benchmark runs // TODO: add some interface to get reports while the benchmark runs
// TODO: make the benchmark optionally multithreaded // TODO: make the benchmark optionally multithreaded
// NOTE: This is blocking, use start to let it run in another thread // NOTE: This is blocking, use start to let it run in another thread
fn bench(n: usize, report: Arc<RwLock<Report>>, solver: SL, builder: GameBuilder<'wl, WL>) -> WResult<Report> { fn bench(
n: usize,
report: Arc<RwLock<Report>>,
solver: SL,
builder: &'wl GameBuilder<'wl, WL>,
) -> WResult<Report> {
(0..n) (0..n)
.into_par_iter() .into_par_iter()
.for_each_with(report.clone(), |outside_data, _i| { .for_each_with(report.clone(), |outside_data, _i| {
let report = outside_data; let report = outside_data;
let r = solver let r = solver
.play(&mut builder.build().expect("could not create game")) .play_owned(builder.build().expect("could not create game"))
.expect("error playing the game during benchmark"); .expect("error playing the game during benchmark");
report.write().expect("lock is poisoned").add(r); report.write().expect("lock is poisoned").add(r);
}); });
@ -63,6 +67,6 @@ where
// PERF: Somehow returning &Report would be better as we don't need to clone then // PERF: Somehow returning &Report would be better as we don't need to clone then
fn report(&'wl self) -> Report; fn report(&'wl self) -> Report;
fn report_shared(&'wl self) -> Arc<RwLock<Report>>; fn report_shared(&'wl self) -> Arc<RwLock<Report>>;
fn start(&'wl self, n: usize) -> WResult<()>; fn start(&'wl self, n: usize, builder: &'wl GameBuilder<'wl, WL>) -> WResult<()>;
fn is_finished(&self) -> bool; fn is_finished(&self) -> bool;
} }

View File

@ -48,9 +48,9 @@ struct Cli {
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
let cli = Cli::parse(); let cli = Cli::parse();
if cli.verbose { if cli.verbose {
Logger::build_mini(Some(Level::DEBUG))?; Logger::builder().set_level(Level::DEBUG).build().unwrap();
} else { } else {
Logger::build_mini(Some(Level::INFO))?; Logger::builder().set_level(Level::INFO).build().unwrap();
} }
trace!("dumping CLI: {:#?}", cli); trace!("dumping CLI: {:#?}", cli);
@ -63,7 +63,7 @@ fn main() -> anyhow::Result<()> {
let bench = BuiltinBenchmark::build(&wl, solver, builder, cli.threads)?; let bench = BuiltinBenchmark::build(&wl, solver, builder, cli.threads)?;
trace!("{bench:#?}"); trace!("{bench:#?}");
bench.start()?; bench.start(50, &bench.builder())?;
loop { loop {
sleep_ms(1000); sleep_ms(1000);

View File

@ -32,9 +32,9 @@ struct Cli {
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
let cli = Cli::parse(); let cli = Cli::parse();
if cli.verbose { if cli.verbose {
Logger::build_mini(Some(Level::TRACE))?; Logger::builder().set_level(Level::DEBUG).build().unwrap();
} else { } else {
Logger::build_mini(Some(Level::INFO))?; Logger::builder().set_level(Level::INFO).build().unwrap();
} }
debug!("dumping CLI: {:#?}", cli); debug!("dumping CLI: {:#?}", cli);

View File

@ -35,9 +35,9 @@ struct Cli {
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
let cli = Cli::parse(); let cli = Cli::parse();
if cli.verbose { if cli.verbose {
Logger::build_mini(Some(Level::TRACE))?; Logger::builder().set_level(Level::DEBUG).build().unwrap();
} else { } else {
Logger::build_mini(Some(Level::INFO))?; Logger::builder().set_level(Level::INFO).build().unwrap();
} }
debug!("dumping CLI: {:#?}", cli); debug!("dumping CLI: {:#?}", cli);

View File

@ -68,6 +68,23 @@ pub trait Solver<'wl, WL: WordList>: Clone + std::fmt::Debug + Sized + Sync {
} }
Ok(resp) Ok(resp)
} }
/// Play a [Game] and return the last [GuessResponse].
///
/// Like [play](Solver::play) but takes an owned game instead of a mutable reference.
///
/// # Errors
///
/// This function will return an error if [make_a_move](Solver::make_a_move) fails.
fn play_owned(&self, mut game: Game<'wl, WL>) -> WResult<GuessResponse> {
let mut resp: GuessResponse;
loop {
resp = self.make_a_move(&mut game)?;
if game.finished() {
break;
}
}
Ok(resp)
}
/// Play a [Game] and return the solution if one was found /// Play a [Game] and return the solution if one was found
/// ///
/// If no solution was found, this function will return [None]. /// If no solution was found, this function will return [None].