full threading and fixes

This commit is contained in:
2026-08-29 10:44:24 -04:00
parent 4f854aeca4
commit d901c9a85d
6 changed files with 248 additions and 123 deletions
+59 -15
View File
@@ -61,7 +61,7 @@ impl Worker {
F: Fn(&BoardState) -> Fut,
Fut: Future<Output = (Vec<f32>, f32)>,
{
println!("game started");
// println!("game started");
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap();
@@ -84,12 +84,11 @@ impl Worker {
// println!("{}", before.elapsed().as_millis());
episode_buffer.push(results);
let temp = if ply_count < 30 { 1.0 } else { 0.0 };
let temp = if ply_count < 30 { 1.0 } else { 0.2 };
let adjusted = apply_temperature(&episode_buffer.last().unwrap().move_dist, temp);
let stm = board_state.board.side_to_move();
let mv = sample_move(&adjusted, &mut rng, stm).unwrap();
let mv = sample_move(&adjusted, &mut rng, &board_state.board).unwrap();
game_hist.push_str(mv.to_string().as_str());
game_hist.push(' ');
@@ -103,6 +102,8 @@ impl Worker {
}
}
println!("game finished: {}", game_hist);
let mut samples: Vec<TrainingSample> = Vec::new();
for result in episode_buffer.iter() {
let stm = result.board_state.board.side_to_move();
@@ -166,14 +167,15 @@ impl Worker {
// }
pub async fn run_worker(self, cmd_rx: Receiver<WorkerCmd>) {
println!("Worker started");
let mut tasks = Vec::new();
// println!("Worker started");
for _ in 0..self.num_games {
let mcts_config = self.mcts_config.clone();
let data_tx = self.data_tx.clone();
let request_tx = self.request_tx.clone();
let device = self.device.clone();
tokio::spawn(async move {
tasks.push(tokio::spawn(async move {
Self::run_game(
self.id,
mcts_config,
@@ -186,19 +188,29 @@ impl Worker {
data_tx,
)
.await;
});
}));
}
loop {
if let Ok(cmd) = cmd_rx.recv() {
match cmd {
// Remove completed tasks.
tasks.retain(|task| !task.is_finished());
// If every game has completed, we're done.
if tasks.is_empty() {
break;
}
match cmd_rx.recv_timeout(Duration::from_millis(10)) {
Ok(cmd) => match cmd {
WorkerCmd::Shutdown => break,
WorkerCmd::Dispatch => {
let mcts_config = self.mcts_config.clone();
let request_tx = self.request_tx.clone();
let device = self.device.clone();
let data_tx = self.data_tx.clone();
tokio::spawn(async move {
tasks.push(tokio::spawn(async move {
Self::run_game(
self.id,
mcts_config,
@@ -211,13 +223,26 @@ impl Worker {
data_tx,
)
.await;
});
}));
}
},
Err(RecvTimeoutError::Timeout) => {
continue;
}
Err(RecvTimeoutError::Disconnected) => {
println!("Request channel disconnected");
break;
}
} else {
panic!("worker dropped inference command");
}
}
for task in tasks {
task.await.expect("Worker game task panicked");
}
println!("Worker {} shut down", self.id);
}
}
@@ -303,13 +328,24 @@ impl NNServer {
pub fn run_server(&self) {
let mut cache: Cache<NNCacheKey, NNResponse> = Cache::new(self.cache_size);
let mut queue: VecDeque<NNRequest> = VecDeque::new();
let mut request_counter: usize = 0;
let mut cache_hits: usize = 0;
let mut batches_ran: usize = 0;
loop {
// Check for shutdown before doing any work.
if let Ok(cmd) = self.command_rx.try_recv() {
match cmd {
NNServerCmd::Shutdown => {
println!("NN server shutting down");
println!(
"NN server shutting down. Served {} requests, with {} cache hits ({:2}%). Ran {} batches (avg {}requests/batch).",
request_counter,
cache_hits,
cache_hits as f64 / request_counter as f64 * 100.0,
batches_ran,
(request_counter - cache_hits) as f64 / batches_ran as f64,
);
break;
} // other commands...
}
@@ -320,7 +356,9 @@ impl NNServer {
if queue.is_empty() {
match self.request_rx.recv_timeout(Duration::from_millis(10)) {
Ok(first) => {
request_counter += 1;
if try_use_cache(first, &mut cache, &mut queue) {
cache_hits += 1;
continue;
}
}
@@ -337,7 +375,11 @@ impl NNServer {
}
while let Ok(req) = self.request_rx.try_recv() {
try_use_cache(req, &mut cache, &mut queue);
request_counter += 1;
if try_use_cache(req, &mut cache, &mut queue) {
cache_hits += 1;
continue;
}
}
let mut jobs_to_send: Vec<NNRequest> = Vec::new();
@@ -359,7 +401,9 @@ impl NNServer {
);
// println!("Sending {} jobs to gpu", jobs_to_send.len());
let (p, v) = self.model.forward(batched_tensor);
batches_ran += 1;
let p_split = p.chunk(jobs_to_send.len(), 0);
let v_split = v.chunk(jobs_to_send.len(), 0);