Feedback on final project proposals in next few days!
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) {
...
return;
}
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);
}
void merge (double[] data, int min, int mid, int max) {
...
}
}
Invoke with pool.invoke(new MTask(data, 0, data.length))
Often Fork-Join pools are not 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
class MaxTask extends RecursiveTask<Double> {
public static int PARALLEL_LIMIT = MaxFinder.DATA_SIZE / 1000;
double[] data;
int min;
int max;
public MaxTask (double[] data, int min, int max) {
this.data = data;
this.min = min;
this.max = max;
}
@Override
protected Double compute () {
if (max - min <= PARALLEL_LIMIT) {
return findMax();
}
MaxTask left = new MaxTask(data, min, min + (max - min) / 2);
MaxTask right = new MaxTask(data, min + (max - min) / 2, max);
right.fork();
double l = left.compute();
double r = right.join();
return Math.max(l, r);
}
private Double findMax() {
double maxValue = Double.MIN_VALUE;
for (int i = min; i < max; ++i) {
if (maxValue < data[i]) {
maxValue = data[i];
}
}
return maxValue;
}
}
public static double findMax(double[] data) {
double max = Double.MIN_VALUE;
for (int i = 0; i < DATA_SIZE; ++i) {
if (max < data[i]) {
max = data[i];
}
}
return max;
}
Compare the run-times of the two methods!
DATA_SIZE
for which MaxTask
is faster?PARALLEL_LIMIT
give better performance?Disclaimer:
findMax
efficientlyWhat did you find?
Simple problem:
double
s, sort it as quickly as possibleArrays.sort(...)
as a baselineDetails to follow…