Sorting by Divide-and-Conquer
Divide-and-Conquer in Parallel:
Many computation problems can be solved efficiently by:
int[] arr of size N
arr contain 1?arr in half1
1
true if step 1 or 2 succeedsint[] arr of size N
arr in increasing orderarr in halfDivide-and-conquer often lends itself well to parallelism:
Idea:
Creating a Fork-Join Pool is easy!
import java.util.concurrent.ForkJoinPool;
...
ForkJoinPool pool = new ForkJoinPool(POOL_SIZE);
...
pool.invoke(new SomeTask(...));
Tasks without return values = recursive action
RecursiveAction classcompute() methodRecursiveAction
import java.util.concurrent.RecursiveAction;
class MSTask extends RecursiveAction {
public MSTask (double[] data, int min, int max) {...}
@Override
protected void compute () {
if (max - min <= 1) {...}
int mid = min + (max - min) / 2
MTask left = new MTask(data, min, mid);
MTask right = new MTask(data, mid, max);
left.fork(); right.fork(); // or can use right.compute()
left.join(); right.join(); // leave out if right.compute()
merge(data, min, mid, max);}}
Invoke with pool.invoke(new MTask(data, 0, data.length))
fork versus compute
The difference:
fork() creates new task to be scheduled by the pool
join
compute() performs computation as part of this task
join necessaryQuestion. Why use one or the other?
ForkJoinPool DoesOften Fork-Join pools are not always as efficient you’d like them to be
To deal with this:
Still FJPs can lead to elegant solutions, readable code
What if we want tasks to return a value?
RecursiveTask<T>!
T
RecursiveAction except compute() returns a T
pool.invoke(someRecursiveTask<T>) now also returns a T
join() method also returns a T
Finding the maximum value in an unsorted array
Compare the run-times of the two methods!
Download fork-join-pools.zip
PARALLEL_LIMIT give better performance?fork/compute compared to fork/fork?Disclaimer:
findMax efficientlySorting networks!