私は分裂と征服戦略によってFactorial関数を実装しようとしています。私はForkJoinフレームワークを使用して、各再帰的タスクをforkして計算を高速化しました。 しかし私はそれが私の期待通りにスピードアップしていないことを発見しました。 ForkJoinを使わずに階数を計算するのに28秒かかりましたが、 はForkJoinを使ったときに25秒かかりました。 これはforkjoinのないコードです:DnCを介した階乗の計算
public static BigInteger factorial(long p, long q) {
if (q < p) {
return new BigInteger("1");
}
if (p == q) {
return new BigInteger("" + p);
}
BigInteger fact = new BigInteger("1");
fact = fact.multiply(factorial(p, (p + q)/2)).multiply(factorial((p + q)/2 + 1, q));
return fact;
}
そして、これはforkJoinとコードです:私は間違っているつもりです
public class Factorial extends RecursiveTask<BigInteger>{
private long p, q;
public Factorial(long p, long q) {
this.p = p;
this.q = q;
}
@Override
public BigInteger compute() {
if(q < p) {
return new BigInteger("1");
}
if(p == q) {
return new BigInteger(""+p);
}
Factorial f1 = new Factorial(p, (p+q)/2);
Factorial f2 = new Factorial((p+q)/2 + 1, q);
f2.fork();
return f1.compute().multiply(f2.join());
}
}
?私はこれがFork/Joinの結果だとは思わない。助けてください!
多くの階乗を計算する必要がある場合は、事前に必要な範囲の階乗を計算してから再利用する必要があります。効率的な方法で同時に階乗計算を同時に行うことはできません。 –
BigIntegerを使う際のパフォーマンスのヒント: '新しいBigInteger(" 1 ")'を定数 'BigInteger.ONE'に置き換えます。 'new BigInteger(" "+ p)'を 'BigInteger.valueOf(p)'に置き換えます。これはより高速であり、可能であれば、以前に作成されたインスタンスを再利用します。 – gb96
@Maurícionの値が大きい場合は、nを計算する並列アルゴリズムを使用します。現在最も速く知られています。 http://www.luschny.de/math/factorial/FastFactorialFunctions.htmのアルゴリズムとベンチマークを参照してください。 – gb96