stuff that does not wörk
cargo devel CI / cargo CI (push) Failing after 1m16s Details

This commit is contained in:
Christoph J. Scherr 2024-04-17 12:39:14 +02:00
parent 932a3f92b0
commit d161b27e42
4 changed files with 85 additions and 25 deletions

View File

@ -1,19 +1,42 @@
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::thread::JoinHandle;
use libpt::log::info; use libpt::log::info;
use crate::error::{BenchError, Error, WResult}; use crate::error::{BenchError, Error, WResult};
use crate::game::{Game, GameBuilder}; use crate::game::{self, Game, GameBuilder};
use crate::solve::Solver; use crate::solve::Solver;
use crate::wlist::WordList; use crate::wlist::WordList;
use super::{Benchmark, Report}; use super::{Benchmark, Report};
#[derive(Debug, Clone)] use rayon::prelude::*;
#[derive(Debug)]
pub struct BuiltinBenchmark<'wl, WL: WordList, SL: Solver<'wl, WL>> { pub struct BuiltinBenchmark<'wl, WL: WordList, SL: Solver<'wl, WL>> {
solver: SL, solver: SL,
builder: GameBuilder<'wl, WL>, builder: GameBuilder<'wl, WL>,
report: Arc<Mutex<Report>>, report: Arc<Mutex<Report>>,
benchth: Option<JoinHandle<()>>,
}
impl<'wl, WL, SL> BuiltinBenchmark<'wl, WL, SL>
where
WL: WordList,
WL: 'wl,
SL: Solver<'wl, WL>,
SL: 'wl,
SL: Send,
{
#[inline]
fn inner_bench(outside_data: (Arc<Mutex<Report>>, GameBuilder<'wl, WL>, SL), _index: usize) {
todo!()
}
fn run_bench(n: usize, report: Arc<Mutex<Report>>, builder: GameBuilder<'wl, WL>, solver: SL) {
(0..n)
.into_par_iter()
.map(|idx| Self::inner_bench((report.clone(), builder.clone(), solver.clone()), idx));
report.lock().expect("lock is poisoned").finalize();
}
} }
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>
@ -22,25 +45,36 @@ where
WL: 'wl, WL: 'wl,
SL: Solver<'wl, WL>, SL: Solver<'wl, WL>,
SL: 'wl, SL: 'wl,
SL: Send,
{ {
fn build( fn build(
wordlist: &'wl WL, _wordlist: &'wl WL,
solver: SL, solver: SL,
builder: GameBuilder<'wl, WL>, builder: GameBuilder<'wl, WL>,
threads: usize threads: usize,
) -> crate::error::WResult<Self> { ) -> crate::error::WResult<Self> {
info!("using {threads} threads for benchmarking"); info!("using {threads} threads for benchmarking");
rayon::ThreadPoolBuilder::new().num_threads(threads).build_global().unwrap(); rayon::ThreadPoolBuilder::new()
.num_threads(threads)
.build_global()
.unwrap();
Ok(Self { Ok(Self {
solver, solver,
report: Arc::new(Mutex::new(Report::new(builder.build()?))), report: Arc::new(Mutex::new(Report::new(builder.build()?))),
builder, builder,
benchth: None,
}) })
} }
fn solver(&self) -> &SL { fn solver(&self) -> SL {
self.solver.clone()
}
fn builder(&'wl self) -> game::GameBuilder<'wl, WL> {
self.builder.clone()
}
fn solver_ref(&'wl self) -> &'wl SL {
&self.solver &self.solver
} }
fn builder(&'wl self) -> &'wl crate::game::GameBuilder<'wl, WL> { fn builder_ref(&'wl self) -> &'wl game::GameBuilder<'wl, WL> {
&self.builder &self.builder
} }
@ -51,4 +85,21 @@ where
fn report(&'wl self) -> super::Report { fn report(&'wl self) -> super::Report {
self.report.lock().expect("lock is poisoned").clone() self.report.lock().expect("lock is poisoned").clone()
} }
fn start(&'wl mut self, n: usize) -> WResult<()> {
let report = self.report_mutex(); // FIXME: needs to keep self borrowed for some reason?
let solver = self.solver();
let builder = self.builder();
let benchth = std::thread::spawn(move || Self::run_bench(n, report, builder, solver));
self.benchth = Some(benchth);
Ok(())
}
fn is_finished(&self) -> Option<bool> {
match &self.benchth {
Some(th) => Some(th.is_finished()),
None => None,
}
}
} }

View File

@ -19,7 +19,7 @@ pub mod builtin;
/// Default amount of games to play for a [Benchmark] /// Default amount of games to play for a [Benchmark]
pub const DEFAULT_N: usize = 50; pub const DEFAULT_N: usize = 50;
pub trait Benchmark<'wl, WL, SL>: Clone + Sized + Debug + Sync pub trait Benchmark<'wl, WL, SL>: Sized + Debug + Sync
where where
WL: WordList, WL: WordList,
WL: 'wl, WL: 'wl,
@ -30,18 +30,24 @@ where
wordlist: &'wl WL, wordlist: &'wl WL,
solver: SL, solver: SL,
builder: GameBuilder<'wl, WL>, builder: GameBuilder<'wl, WL>,
threads: usize threads: usize,
) -> crate::error::WResult<Self>; ) -> crate::error::WResult<Self>;
fn builder(&'wl self) -> &'wl GameBuilder<'wl, WL>; fn builder(&'wl self) -> GameBuilder<'wl, WL>;
fn builder_ref(&'wl self) -> &'wl GameBuilder<'wl, WL>;
fn make_game(&'wl self) -> WResult<Game<'wl, WL>> { fn make_game(&'wl self) -> WResult<Game<'wl, WL>> {
Ok(self.builder().build()?) Ok(self.builder_ref().build()?)
} }
fn solver(&'wl self) -> &'wl SL; fn solver(&'wl self) -> SL;
fn solver_ref(&'wl self) -> &'wl SL;
fn play(&'wl self) -> WResult<GuessResponse> { fn play(&'wl self) -> WResult<GuessResponse> {
self.solver().play(&mut self.make_game()?) self.solver_ref().play(&mut self.make_game()?)
} }
fn start(&'wl mut self, n: usize) -> WResult<()>;
fn is_finished(&self) -> Option<bool>;
// 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
#[deprecated]
fn bench(&'wl self, n: usize) -> WResult<Report> { fn bench(&'wl self, n: usize) -> WResult<Report> {
let report = self.report_mutex(); let report = self.report_mutex();
let this = std::sync::Arc::new(self); let this = std::sync::Arc::new(self);

View File

@ -142,8 +142,12 @@ impl Display for Report {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!( write!(
f, f,
"n: {}, win_ratio: {:.2}%, avg_score: {:.4} steps until finish, avgerage time per game: {}μs, \n\ "n: {}\n\
rating: {:.4}, full time until completion: {}ms win_ratio: {:.2}%\n\
avg_score: {:.4}\n\
avgerage time per game: {}μs\n\
full time until completion: {}ms\n\
rating: {:.4}\n\
", ",
self.n(), self.n(),
self.avg_win() * 100.0, self.avg_win() * 100.0,

View File

@ -11,7 +11,8 @@ use wordle_analyzer::bench::builtin::BuiltinBenchmark;
use wordle_analyzer::bench::report::Report; use wordle_analyzer::bench::report::Report;
use wordle_analyzer::bench::{Benchmark, DEFAULT_N}; use wordle_analyzer::bench::{Benchmark, DEFAULT_N};
use wordle_analyzer::error::WResult; use wordle_analyzer::error::WResult;
use wordle_analyzer::solve::{BuiltinSolverNames, Solver}; use wordle_analyzer::game::GameBuilder;
use wordle_analyzer::solve::{AnyBuiltinSolver, BuiltinSolverNames, Solver};
use wordle_analyzer::wlist::builtin::BuiltinWList; use wordle_analyzer::wlist::builtin::BuiltinWList;
use wordle_analyzer::{self, game}; use wordle_analyzer::{self, game};
@ -54,24 +55,22 @@ fn main() -> anyhow::Result<()> {
trace!("dumping CLI: {:#?}", cli); trace!("dumping CLI: {:#?}", cli);
let wl = BuiltinWList::default(); let wl = BuiltinWList::default();
let builder = game::Game::builder(&wl) let builder: GameBuilder<'_, BuiltinWList> = game::Game::builder(&wl)
.length(cli.length) .length(cli.length)
.max_steps(cli.max_steps) .max_steps(cli.max_steps)
.precompute(cli.precompute); .precompute(cli.precompute);
let solver = cli.solver.to_solver(&wl); let solver: AnyBuiltinSolver<'_, BuiltinWList> = cli.solver.to_solver(&wl);
let bench = Arc::new(BuiltinBenchmark::build(&wl, solver, builder, cli.threads)?); let mut bench = BuiltinBenchmark::build(&wl, solver, builder, cli.threads)?;
let bench_running = bench.clone();
trace!("{bench:#?}"); trace!("{bench:#?}");
let n = cli.n; let n = cli.n;
let bench_th: std::thread::JoinHandle<WResult<Report>> = bench.start(n)?;
std::thread::spawn(move || bench_running.bench(n));
while !bench_th.is_finished() { while !bench.is_finished()? {
println!("{}", bench.report()); println!("{}", bench.report());
} }
// finished report
println!("{}", bench_th.join().expect("thread go boom")?);
// FIXME: Rustc thinks wl is borrowed at this point, but it is not!!!!! Or at least it should
// not be
Ok(()) Ok(())
} }