I have the following toy Rust program:
use rayon::prelude::*;
use std::{env, thread, time};
/// Sleeps 1 second n times
fn seq_sleep(n: usize) {
for _ in 0..n {
thread::sleep(time::Duration::from_millis(1000));
}
}
/// Launches n threads that sleep 1 second
fn thread_sleep(n: usize) {
let mut handles = Vec::new();
for _ in 0..n {
handles.push(thread::spawn(|| {
thread::sleep(time::Duration::from_millis(1000))
}));
}
for handle in handles {
handle.join().unwrap();
}
}
/// Sleeps 1 seconds n times parallely using rayon
fn rayon_sleep(n: usize) {
let millis = vec![0; n];
millis
.par_iter()
.for_each(|_| thread::sleep(time::Duration::from_millis(1000)));
}
fn main() {
let args: Vec<String> = env::args().collect();
let n = args[1].parse::<usize>().unwrap();
let now = time::Instant::now();
seq_sleep(n);
println!("sequential: {:?}", now.elapsed());
let now = time::Instant::now();
thread_sleep(n);
println!("thread: {:?}", now.elapsed());
let now = time::Instant::now();
rayon_sleep(n);
println!("rayon: {:?}", now.elapsed());
}
Basically, I want to compare the degree of parallelism of i) sequential code, ii) basic threads, and iii) rayon. To do so, my program accepts one input parameter n
and, depending on the method, it sleeps for 1 second n
times.
For n
= 8, I get the following output:
sequential: 8.016809707s
thread: 1.006029845s
rayon: 1.004957395s
So far so good. However, for n
= 9, I get the following output:
sequential: 9.012422104s
thread: 1.003085005s
rayon: 2.011378713s
The sequential and basic thread versions make sense to me. However, I expected rayon to take 1 second. My machine has 4 cores and hyper threading. This leads me to think that rayon internally limits the number of parallel threads according to the cores/threads that your machine supports. Is this correct?
Yes:
rayon::ThreadPoolBuilder::build_global()
:
Initializes the global thread pool. This initialization is optional. If you do not call this function, the thread pool will be automatically initialized with the default configuration.
rayon::ThreadPoolBuilder::num_threads()
:
If
num_threads
is 0, or you do not call this function, then the Rayon runtime will select the number of threads automatically. At present, this is based on theRAYON_NUM_THREADS
environment variable (if set), or the number of logical CPUs (otherwise). In the future, however, the default behavior may change to dynamically add or remove threads as needed.