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 - `single thread`: No multi-threading or any optimization of any kind. Used as
a reference. 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 - `rayon`: Multi-threading provided by the `rayon` crate, but no optimization
of any kind. Used as a reference. of any kind. Used as a reference.
- `rayon sorted`: Multi-threading provided by the `rayon` crate. Tasks are - `rayon sorted`: Multi-threading provided by the `rayon` crate. Tasks are
sorted so the shortest ones are executed first. sorted so the shortest ones are executed first.
- `rayon sorted reverse`: Multi-threading provided by the `rayon` crate. Tasks - `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 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 - `rayon sorted reverse`: Similar to `rayon sorted reverse`, but tasks are
sorted from shortest to longest and are then iterated in the reverse order. 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_DATA: &[(&str, &[Task])] = &[("10 tasks", T_10), ("500 tasks", T_500)];
const TEST_FUNCS: &[(&str, &dyn Fn(&[Task]))] = &[ const TEST_FUNCS: &[(&str, &dyn Fn(&[Task]))] = &[
("single thread", &single_thread), ("single thread", &single_thread),
("multi threads", &multi_threads),
("lpt", &lpt),
("rayon", &rayon), ("rayon", &rayon),
("rayon sorted", &rayon_sorted), ("rayon sorted", &rayon_sorted),
("rayon sorted reverse", &rayon_sorted_reverse), ("rayon sorted reverse", &rayon_sorted_reverse),

View file

@ -1,5 +1,7 @@
mod lpt;
mod rayon; mod rayon;
mod single_thread; mod single_thread;
pub use lpt::*;
pub use rayon::*; pub use rayon::*;
pub use single_thread::single_thread; 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();
}
}