Fork/Join Tutorialを見た後、大きな階乗を計算するためのクラスを作成しました。
public class ForkFactorial extends RecursiveTask<BigInteger> {
final int end;
final int start;
private static final int THRESHOLD = 10;
public ForkFactorial(int n) {
this(1, n + 1);
}
private ForkFactorial(int start, int end) {
this.start = start;
this.end = end;
}
@Override
protected BigInteger compute() {
if (end - start < THRESHOLD) {
return computeDirectly();
} else {
int mid = (start + end) / 2;
ForkFactorial lower = new ForkFactorial(start, mid);
lower.fork();
ForkFactorial upper = new ForkFactorial(mid, end);
BigInteger upperVal = upper.compute();
return lower.join().multiply(upperVal);
}
}
private BigInteger computeDirectly() {
BigInteger val = BigInteger.ONE;
BigInteger mult = BigInteger.valueOf(start);
for (int iter = start; iter < end; iter++, mult = mult.add(BigInteger.ONE)) {
val = val.multiply(mult);
}
return val;
}
}
私が持っている質問は、タスクを細分化するしきい値をどのように決定するかです。フォーク/ジョインの並列処理に関するページを見つけました。
fork/join 並列処理を使用するアルゴリズムを実装する際に考慮すべき主な事項の 1 つは、並列サブタスクを fork するのではなく、タスクが順次計算を実行するかどうかを決定するしきい値を選択することです。
しきい値が大きすぎると、プログラムは使用可能なプロセッサ/コアを十分に活用するのに十分なタスクを作成しない可能性があります。
しきい値が小さすぎると、タスクの作成と管理のオーバーヘッドが大きくなる可能性があります。
一般に、適切なしきい値を見つけるには、いくつかの実験が必要です。
では、しきい値を決定するには、どのような実験を行う必要があるでしょうか?