elo: multithreading improvements

This commit is contained in:
Simon Gardling 2025-03-03 11:06:24 -05:00
parent c368ffc495
commit 6d920ce5af
Signed by: titaniumtown
GPG Key ID: 9AB28AC10ECE533D
2 changed files with 20 additions and 24 deletions

View File

@ -4,7 +4,8 @@ use std::io;
use std::io::prelude::*; use std::io::prelude::*;
#[allow(dead_code)] #[allow(dead_code)]
pub trait Agent { // implements `Send` so we can use it in a multithreaded `EloArena`
pub trait Agent: Send {
/// Returns the move of an [`Agent`] /// Returns the move of an [`Agent`]
fn next_move(&mut self, board: &Board) -> Option<CoordPair>; fn next_move(&mut self, board: &Board) -> Option<CoordPair>;
/// Returns the name of the [`Agent`] /// Returns the name of the [`Agent`]

View File

@ -65,23 +65,19 @@ pub fn run() {
), ),
]); ]);
// for _ in 0..100 { arena.play(
// arena.prop_arena(); &(0..arena.players.len())
// } .zip([0].into_iter().cycle())
.filter(|(i, j)| i != j)
for _ in 0..20 { .collect::<Vec<_>>()
arena.play_all_against(0); .repeat(20),
} );
// for _ in 0..2 {
// arena.play_two(1, 2);
// }
println!("{}", arena); println!("{}", arena);
} }
pub struct PlayerArena { pub struct PlayerArena {
/// Name, Creator, Elo, freq (mod) /// Name, Creator, Elo
players: Vec<(String, Box<dyn Fn(Piece) -> Box<dyn Agent>>, EloRating)>, players: Vec<(String, Box<dyn Fn(Piece) -> Box<dyn Agent>>, EloRating)>,
} }
@ -124,27 +120,26 @@ impl PlayerArena {
) )
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()
// .into_iter() // after the agents are created, we can multithread the games being played
.into_par_iter() .into_par_iter()
.map(|((i, j), (p1, p2))| (i, j, Self::play_two_inner(p1, p2))) .map(|((i, j), (p1, p2))| (i, j, Self::play_two_inner(p1, p2)))
.collect::<Vec<_>>() .collect::<Vec<_>>()
// collect and process the outcomes of all the games
.into_iter() .into_iter()
.for_each(|(i, j, o)| self.process_outcome(i, j, &o)); .for_each(|(i, j, o)| self.process_outcome(i, j, &o));
} }
fn play_all_against(&mut self, i: usize) { fn prop_arena(&mut self) {
self.play( self.play(
&(0..self.players.len()) &(0..self.players.len())
.zip([i].into_iter().cycle()) .flat_map(|i| {
(0..self.players.len())
.map(move |j| (i, j))
.filter(|(i, j)| i != j) .filter(|(i, j)| i != j)
.collect::<Vec<_>>()
})
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
) );
}
fn prop_arena(&mut self) {
for i in 0..self.players.len() {
self.play_all_against(i);
}
} }
fn process_outcome(&mut self, player1: usize, player2: usize, outcome: &Outcomes) { fn process_outcome(&mut self, player1: usize, player2: usize, outcome: &Outcomes) {