There's more...

The underlying mechanism of rayon is work stealing. This means that when we call the following function, the current thread will immediately start working on a and place b in a queue:

rayon::join(a, b);

Meanwhile, whenever a core is idle, rayon will let it work on the next task in the queue. The new thread then steals the task from the others. In our case, that would be b. If a happens to finish before b, the main thread will look into the queue and try to steal work as well. The queue can contain more than two items if rayon::join is called multiple times in a recursive function.

The author of rayon, Niko Matsakis, wrote down the following pseudo Rust code to illustrate this principle in his introductory blog post at http://smallcultfollowing.com/babysteps/blog/2015/12/18/rayon-data-parallelism-in-rust/:

fn join<A,B>(oper_a: A, oper_b: B)
where A: FnOnce() + Send,
B: FnOnce() + Send,
{
// Advertise `oper_b` to other threads as something
// they might steal:
let job = push_onto_local_queue(oper_b);

// Execute `oper_a` ourselves:
oper_a();

// Check whether anybody stole `oper_b`:
if pop_from_local_queue(oper_b) {
// Not stolen, do it ourselves.
oper_b();
} else {
// Stolen, wait for them to finish. In the
// meantime, try to steal from others:
while not_yet_complete(job) {
steal_from_others();
}
result_b = job.result();
}
}

By the way, the recursive Fibonacci implementation provided in this example [34] is easy to look at and illustrates the point of using rayon::join, but is also really, really inefficient. To learn why, and how to improve on it, check out the Chapter 10Using Experimental Nightly FeaturesBenchmarking your code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.220.174.191