-
Notifications
You must be signed in to change notification settings - Fork 577
Description
I was playing around with in_place_scope to try to offload some work while not blocking the main threadpool, and not blocking the worker pool with long-running main pool tasks. From reading the documentation, I thought in_place_scope would be a drop in replacement for scope with the behaviour I wanted.
Running this code produces surprising output that, before digging deeper, appears to contradict the documentation.
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use rayon::ThreadPoolBuilder;
fn main() {
let pool = ThreadPoolBuilder::new()
.thread_name(|u| format!("pool thread {u}"))
.build()
.unwrap();
let stuff = vec![0; 5];
println!("Scope");
pool.scope(|_| {
stuff
.par_iter()
.for_each(|_| println!("Running in thread {:?}", std::thread::current().name()))
});
println!("Scope in place");
pool.in_place_scope(|_| {
stuff
.par_iter()
.for_each(|_| println!("Running in thread {:?}", std::thread::current().name()))
});
}I initially expected both runs to produce the same output, modulo the specific thread numbers, but I was surprised to find they ran their tasks on different pools.
Scope
Running in thread Some("pool thread 30")
Running in thread Some("pool thread 1")
Running in thread Some("pool thread 27")
Running in thread Some("pool thread 26")
Running in thread Some("pool thread 28")
Scope in place
Running in thread None
Running in thread None
Running in thread None
Running in thread None
Running in thread None
From reading other issues around in_place_scope it's probably infeasible to change how it functions, but I was surprised by the current behaviour even after I'd read the documentation. The documentation is at least unclear if you're not aware of the internals of rayon: This is just like scope() except the closure runs on the same thread that calls in_place_scope(). Only work that it spawns runs in the thread pool. Reading that, it's not immediately obvious that parallel iterators don't count as "spawning" and only scope.spawn() calls count, and it's definitely a subtle distinction between in_place_scope and install/scope.