Rayon: data paralellism in Rust
smallcultfollowing.com
smallcultfollowing.com
Also the joins don't sync data together, they wait for all threads to finish. That is not directly what Amdahl's law is about.
Using this style of parallelism creates many bubbles that each condense down to a single point every time you call join(), similar to a beaded necklace. This means that the 'p' in Amdahl's law for the percentage of time spent in parallel tasks is already stunted from the blocks of sequential code (or necklace string) caused by the joins.
Futures and workstealing parallel execution are two techniques that work hand in hand.
Practically it can't be compared with C++ annotated OpenMP for loops, which have an implicit join at the loop termination. In a parallel data flow system like Rayon there are no implicit joins, only explicit as required. join() in this system is more like return dataflow as show in the presentation you link too.
The nice thing is that join is recursive in the quicksort example and that means its equivalent to the await await syntax in practical terms. Which also means when both are finished it will return.
let mid = partition(v);
let (lo, hi) = v.split_at_mut(mid);
Future:of(|| quick_sort::<J,T>(lo)).await(),
Future:of(|| quick_sort::<J,T>(hi)).await());
Is exactly the same in parallelism as this let mid = partition(v);
let (lo, hi) = v.split_at_mut(mid);
J::join(|| quick_sort::<J,T>(lo),
|| quick_sort::<J,T>(hi));
Except that join gives better scheduling due to work stealing which will avoid unbalanced cpu usage.My Rust is non existent but conceptually Rayon is similar to java9 parallel streams which I know well.
And that's why this isn't directly related to Amdalh's law, which is about data synchronization. If something is parallel yet not concurrent it doesn't need to be synchronized. So what you are describing is a pragmatic hangup.