Compare commits

...

2 commits

Author SHA1 Message Date
Rodolphe Bréard
2038cb93ee Add the multi_threads algorithm 2024-10-30 23:39:03 +01:00
Rodolphe Bréard
7fc15efb1a Add the LPT algorithm 2024-10-30 23:22:44 +01:00
4 changed files with 51 additions and 1 deletions

View file

@ -65,13 +65,17 @@ algorithms in Rust and benchmark them. Let the battle begin.
- `single thread`: No multi-threading or any optimization of any kind. Used as
a reference.
- `multi threads`: Manual multi-threading but no optimization of any kind. Used
as a reference.
- `lpt`: Manual multi-threading. Tasks are sorted so the shortest ones are
executed first. This is the [longest-processing-time-first algorithm][lpt].
- `rayon`: Multi-threading provided by the `rayon` crate, but no optimization
of any kind. Used as a reference.
- `rayon sorted`: Multi-threading provided by the `rayon` crate. Tasks are
sorted so the shortest ones are executed first.
- `rayon sorted reverse`: Multi-threading provided by the `rayon` crate. Tasks
are sorted so the longest ones are executed first. This should behave as an
[LPT][lpt].
LPT.
- `rayon sorted reverse`: Similar to `rayon sorted reverse`, but tasks are
sorted from shortest to longest and are then iterated in the reverse order.

View file

@ -6,6 +6,8 @@ use rust_job_scheduling::Task;
const TEST_DATA: &[(&str, &[Task])] = &[("10 tasks", T_10), ("500 tasks", T_500)];
const TEST_FUNCS: &[(&str, &dyn Fn(&[Task]))] = &[
("single thread", &single_thread),
("multi threads", &multi_threads),
("lpt", &lpt),
("rayon", &rayon),
("rayon sorted", &rayon_sorted),
("rayon sorted reverse", &rayon_sorted_reverse),

View file

@ -1,5 +1,7 @@
mod lpt;
mod rayon;
mod single_thread;
pub use lpt::*;
pub use rayon::*;
pub use single_thread::single_thread;

42
src/algorithm/lpt.rs Normal file
View file

@ -0,0 +1,42 @@
use crate::Task;
use std::sync::{Arc, Mutex};
use std::thread;
pub fn lpt(data: &[Task]) {
let mut data = data.to_vec();
data.sort();
run_multi(data);
}
pub fn multi_threads(data: &[Task]) {
let data = data.to_vec();
run_multi(data);
}
#[inline(always)]
fn run_multi(data: Vec<Task>) {
let data_mt = Arc::new(Mutex::new(data));
let nb_threads = thread::available_parallelism()
.map(|n| n.get())
.unwrap_or(1);
let mut handles = Vec::with_capacity(nb_threads);
for _ in 0..nb_threads {
let dt = data_mt.clone();
let h = thread::spawn(move || loop {
let mut data = dt.lock().unwrap();
let task = match data.pop() {
Some(t) => t,
None => {
break;
}
};
std::mem::drop(data);
task.execute();
});
handles.push(h);
}
for h in handles {
let _ = h.join();
}
}