public class Fibonacci {
public static class PFibo extends Thread {
private int x;
public long answer;
public PFibo(int x) {
this.x = x;
}
public void run() {
if (x <= 2)
answer = 1;
else {
try {
PFibo t = new PFibo(x - 1);
t.start();
long y = RFibo(x - 2);
t.join();
answer = t.answer + y;
} catch (InterruptedException ex) {
}
}
}
}
public static long RFibo(int no) {
if (no == 1 || no == 2) {
return 1;
}
return RFibo(no - 1) + RFibo(no - 2);
}
public static void main(String[] args) throws Exception {
try {
long start = System.currentTimeMillis();
PFibo f = new PFibo(30);
f.start();
f.join();
long end = System.currentTimeMillis();
System.out.println("Parallel-Fibonacci:" + f.answer + "\tTime:" + (end - start));
start = System.currentTimeMillis();
long result = RFibo(30);
end = System.currentTimeMillis();
System.out.println("Normal-Fibonacci:" + result + "\tTime:" + (end - start));
} catch (Exception e) {
}
}
}
我目前正在阅读多线程算法&#39;来自&#39;算法导论&#39;。我尝试实现一个基本的多线程程序来计算第n个斐波纳契数。对于n = 30,程序给出了以下输出:
Parallel-Fibonacci:832040 Time:10
Normal-Fibonacci:832040 Time:3
为什么并行版本比非并行版本慢。有线程切换或者线程数太多&#39;放慢了速度?
加速并行版本必须遵循什么方法?
答案 0 :(得分:1)
是否有线程切换或者线程数太多&#39;放慢了速度?
当然可以。在许多方面 -
正如评论中已经指出的那样
PFibo t = new PFibo(x - 1);
t.start();
有效地,您为PFibo(30)
创建了大约28个主题,这意味着用于评估每个词的一个上下文切换
join()
方法,每次你创建/开始一个新线程,即最终它已成为连续剧。
所以最终费用 =实际序列方法的成本RFibo(n)
+围绕n个上下文切换+同步时间(join()
所用的时间)
加速并行版本必须遵循什么方法?
我会说,不要这样做。斐波那契系列&#39;解决方案模式不适合通过并行性进行优化。只需依靠串行版本(您可以实现迭代版本以提高效率)。
答案 1 :(得分:0)
您的输入太小,无法从并行性中获得任何好处。尽管如此,并行化此版本的Fibonacci算法还是有意义的。您的算法是指数的。通过创建新线程,您可以在线程之间分配指数级工作。但是请注意,确实存在一个线性时间算法来计算斐波那契数,正如这里的人们已经说过的那样,最好按顺序运行。因此,在您的实现中使用较大的输入,我得到的是Intel 2.3GHz:
$ java Fib 30
Parallel-Fib:832040 Time:0.026805616
Sequential-Fib:832040 Time:0.002786453
$ java Fib 33
Parallel-Fib:3524578 Time:0.012451416
Sequential-Fib:3524578 Time:0.012420652
$ java Fib 36
Parallel-Fib:14930352 Time:0.035997556
Sequential-Fib:14930352 Time:0.056066557
$ java Fib 44
Parallel-Fib:701408733 Time:2.037292083
Sequential-Fib:701408733 Time:3.050315551