From 14e55e8c5c42bbc4ebf7de2c8172e7731bd8b294 Mon Sep 17 00:00:00 2001 From: Fabian Schmidt Date: Tue, 9 Apr 2024 15:07:55 +0200 Subject: [PATCH] not working multi threaded solution --- rust/src/main.rs | 87 +++++++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 35 deletions(-) diff --git a/rust/src/main.rs b/rust/src/main.rs index a515ef7..fecb74a 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -2,55 +2,72 @@ use std::{ collections::HashMap, fs::File, io::{BufRead, BufReader}, + sync::{Arc, Mutex, MutexGuard}, + thread, }; struct StationMeasurements { min: f64, max: f64, - temps: Vec, + count: usize, + sum: f64, } fn main() { - let mut stations: HashMap = HashMap::new(); + let stations: Arc>> = + Arc::new(Mutex::new(HashMap::new())); + + let cores: usize = std::thread::available_parallelism().unwrap().into(); let file = File::open("../measurements.txt").expect("File measurements.txt not found"); let reader = BufReader::new(file); - let mut line_num = 0; - for line_result in reader.lines() { - line_num += 1; - if line_num % 50000 == 0 { - println!("Calculated {line_num} stations"); - } - let line = line_result.expect("could not read line"); - let (station, temp) = line.split_once(';').unwrap(); - let temp = temp.parse().unwrap(); - let measurements_option = stations.get_mut(station); - if let Some(measurements) = measurements_option { - if temp < measurements.min { - measurements.min = temp; - } else if temp > measurements.max { - measurements.max = temp; + let lines = Arc::new(Mutex::new(reader.lines())); + let chunk_length = 1_000_000_000 / cores; + let mut handles = vec![]; + for _i in 0..cores { + let stations_clone = stations.clone(); + let lines_clone = lines.clone(); + let handle = thread::spawn(move || { + let lines_guard = lines_clone.lock().unwrap(); + let chunk = lines_guard.take(chunk_length); + lines_guard.skip(chunk_length); + for line_result in chunk { + let line = line_result.expect("could not read line"); + let (station, temp) = line.split_once(';').unwrap(); + let temp = temp.parse().unwrap(); + let mut stations_guard = stations_clone.lock().unwrap(); + let measurements_option = stations_guard.get_mut(station); + if let Some(measurements) = measurements_option { + if temp < measurements.min { + measurements.min = temp; + } else if temp > measurements.max { + measurements.max = temp; + } + measurements.count += 1; + measurements.sum += temp; + } else { + let measurements = StationMeasurements { + min: temp, + max: temp, + count: 1, + sum: temp, + }; + stations_clone + .lock() + .unwrap() + .insert(station.to_owned(), measurements); + } } - measurements.temps.push(temp); - } else { - let measurements = StationMeasurements { - min: temp, - max: temp, - temps: vec![temp], - }; - stations.insert(station.to_owned(), measurements); - } + }); + handles.push(handle); } - for (station, measurments) in stations { + for handle in handles { + handle.join().unwrap(); + } + for (station, measurments) in stations.lock().unwrap().iter() { let min = measurments.min; let max = measurments.max; - let avg = avg(measurments.temps); - println!("{station}={min}/{max}/{avg}"); + let avg = measurments.sum / measurments.count as f64; + println!("{station}={min}/{max}/{avg:.2}"); } } - -fn avg(temps: Vec) -> f64 { - let num_temps = temps.len() as f64; - let sum_temps: f64 = temps.iter().sum(); - sum_temps / num_temps -}