From 6d920ce5af19aee5df4cb9c2994a4792cb7ead84 Mon Sep 17 00:00:00 2001 From: Simon Gardling Date: Mon, 3 Mar 2025 11:06:24 -0500 Subject: [PATCH] elo: multithreading improvements --- src/agent.rs | 3 ++- src/elo.rs | 41 ++++++++++++++++++----------------------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/agent.rs b/src/agent.rs index 5e146e1..003648c 100644 --- a/src/agent.rs +++ b/src/agent.rs @@ -4,7 +4,8 @@ use std::io; use std::io::prelude::*; #[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`] fn next_move(&mut self, board: &Board) -> Option; /// Returns the name of the [`Agent`] diff --git a/src/elo.rs b/src/elo.rs index 354e95f..48acbc0 100644 --- a/src/elo.rs +++ b/src/elo.rs @@ -65,23 +65,19 @@ pub fn run() { ), ]); - // for _ in 0..100 { - // arena.prop_arena(); - // } - - for _ in 0..20 { - arena.play_all_against(0); - } - - // for _ in 0..2 { - // arena.play_two(1, 2); - // } + arena.play( + &(0..arena.players.len()) + .zip([0].into_iter().cycle()) + .filter(|(i, j)| i != j) + .collect::>() + .repeat(20), + ); println!("{}", arena); } pub struct PlayerArena { - /// Name, Creator, Elo, freq (mod) + /// Name, Creator, Elo players: Vec<(String, Box Box>, EloRating)>, } @@ -124,27 +120,26 @@ impl PlayerArena { ) }) .collect::>() - // .into_iter() + // after the agents are created, we can multithread the games being played .into_par_iter() .map(|((i, j), (p1, p2))| (i, j, Self::play_two_inner(p1, p2))) .collect::>() + // collect and process the outcomes of all the games .into_iter() .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( &(0..self.players.len()) - .zip([i].into_iter().cycle()) - .filter(|(i, j)| i != j) + .flat_map(|i| { + (0..self.players.len()) + .map(move |j| (i, j)) + .filter(|(i, j)| i != j) + .collect::>() + }) .collect::>(), - ) - } - - 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) {