这个python代码有什么问题吗?为什么它比ruby运行得慢?

这个python代码有什么问题吗?为什么它比ruby运行得慢?,python,ruby,performance,fibonacci,Python,Ruby,Performance,Fibonacci,我对比较ruby和python的速度感兴趣,所以我采用了最简单的递归计算,即打印斐波那契序列 这是python代码 #!/usr/bin/python2.7 def fib(n): if n == 0: return 0 elif n == 1: return 1 else: return fib(n-1)+fib(n-2) i = 0 while i < 35:

我对比较ruby和python的速度感兴趣,所以我采用了最简单的递归计算,即打印斐波那契序列

这是python代码

#!/usr/bin/python2.7                       
def fib(n):
    if n == 0: 
        return 0
    elif n == 1:
        return 1 
    else:
        return fib(n-1)+fib(n-2)

i = 0
while i < 35:
    print fib(i)
    i = i + 1
这是ruby的,现在python2.7给出了

real    0m11.605s
user    0m11.563s
sys     0m0.013s

这是怎么回事?

因此对于这段代码,Python的速度比Ruby慢了一倍多。对于其他代码,Python可能比Ruby快

fib()的实现具有指数级的运行时间。这可以通过使用循环轻松避免。Python示例:

a, b = 1, 1
for i in range(35):
    a, b = b, a+b
print b

你计算斐波那契数列前35个数字的方法效率极低。函数fib()运行35次,每次fib()都有指数级的运行时间。Python中的生成器是这个问题的完美解决方案,并且比Ruby中编写的生成器效率更高

def fibo_generator(n):
    # gets Fibonacci numbers up to nth number using a generator
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b
然后,您可以使用以下代码打印最大为35的所有斐波那契数:

for f in fibo_generator(35):
    print f
这是迄今为止在Python中实现斐波那契序列最有效的方法,也是最通用的方法

我对比较ruby很感兴趣 速度vs python

微基准是比较语言的一种非常糟糕的方法,尤其是在你掌握这两种语言之前。如果你想要一个具有现实意义的基准,那么你需要投入大量的精力——或者你自己


这里是一个更好的比较python的递归效率是造成这种开销的原因。有关更多详细信息,请参阅。上述以迭代方式解决此问题的解决方案更适合python,因为它们不会产生递归所产生的函数调用开销。我对ruby的假设是,它显然是在优化代码,而python不是。同样,这篇文章使用几乎相同的fib函数对此进行了详细介绍。

这里还有一些数字需要比较:

Python2.7 9.67 user 0.09 system 0:09.78 elapsed 99%CPU (0avgtext+0avgdata 16560maxresident)k 0inputs+0outputs (0major+1169minor)pagefaults 0swaps ruby 1.8.7 (2010-06-23 patchlevel 299) [x86_64-linux] 28.37 user 0.35 system 0:28.78 elapsed 99% CPU (0avgtext+0avgdata 9200maxresident)k 1896inputs+0outputs (9major+656minor)pagefaults 0swaps ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-linux] 6.21 user 0.08 system 0:06.36 elapsed 98% CPU (0avgtext+0avgdata 14160maxresident)k 4416inputs+0outputs (16major+953minor)pagefaults 0swaps 蟒蛇2.7 9.67用户0.09系统0:09.78运行99%CPU(0avgtext+0avgdata 16560maxresident)k 0输入+0输出(0主要+1169次要)页面故障0交换 ruby 1.8.7(2010-06-23补丁级别299)[x86_64-linux] 28.37用户0.35系统0:28.78运行99%CPU(0avgtext+0avgdata 9200maxresident)k 1896输入+0输出(9主+656小)页面故障0交换 ruby 1.9.2p0(2010-08-18修订版29036)[x86_64-linux] 6.21用户0.08系统0:06.36运行98%CPU(0avgtext+0avgdata 14160maxresident)k 4416输入+0输出(16主要+953最小)页面故障0交换 对于提供的代码,Python比ruby1.8快三倍,比ruby1.9.1慢30%

用于比较的其他Python版本:

2.4.6 took 10.30 seconds 2.5.5 took 9.93 seconds 2.6.6 took 9.22 seconds 2.7 took 9.35 seconds 3.0.1 took 11.67 seconds 3.1.2 took 11.35 seconds 3.2a3+ (py3k:85895, Oct 29 2010, 01:41:57) [GCC 4.4.5] took 13.09 seconds 2.5.2 (77963, Oct 15 2010, 02:00:43) [PyPy 1.3.0] took 21.26 seconds 2.5.1 (Release_2_5_1:6813, Sep 26 2009, 13:47:54) [OpenJDK 64-Bit Server VM (Sun Microsystems Inc.)] took 8.81 seconds 2.4.6耗时10.30秒 2.5.5用了9.93秒 2.6.6用了9.22秒 2.7用了9.35秒 3.0.1用了11.67秒 3.1.2耗时11.35秒 3.2a3+(py3k:858952010年10月29日01:41:57) [GCC 4.4.5]耗时13.09秒 2.5.2(779632010年10月15日02:00:43) [PyPy 1.3.0]耗时21.26秒 2.5.1(发布时间:2009年9月26日13:47:54) [OpenJDK 64位服务器虚拟机(Sun Microsystems Inc.)]耗时8.81秒
我只想指出,在独立于语言的意义上,迭代计算会快得多。在这里使用递归会导致反复计算相同的值。我不会列出答案,因为我不知道确切的原因,但ruby编译器可能有一些Python编译器没有的优化。使用递归的朴素fib函数会创建一些语言无法很好处理的巨大调用堆栈。特别是,该语言通常必须实现尾部调用递归优化,以有效地处理此类情况,并且在大量递归下不会出现堆栈溢出。这可能是密切相关的:@Codex:这里没有什么可优化的。这个定义不是尾部递归的,为什么要循环呢
fibo=lambda n:int(((1+math.sqrt(5))/2)**n+(1/((1+math.sqrt(5))/2))**n)/math.sqrt(5)+0.5)
我不想要编程语言x的效率最高,我想知道为什么几乎完全相同的python和ruby程序运行在非常不同的时间框架内。ruby版本在我背后优化代码吗?当我们在做这个测试的时候,我认为记忆化会立即加快速度。关于为什么这个测试没有任何意义,请参阅THC4k的答案。这并不意味着Python比Ruby慢,因为您的应用程序没有多大意义。你为什么要用任何一种语言做一些低效的事情?当你发挥Python的优势时,它是最快的,Ruby也是。为什么这是一种比较语言的糟糕方法?与python中几乎相同的代码相比,ruby速度更快的原因是什么?我知道人们可以使用生成器、备忘录等工具来更好地提供序列。。。但是我感兴趣的是什么?为什么相同的代码会有这么大的差异?@AntonioP:因为只有初学者才会写这样的代码。您的基准测试只告诉您“这个糟糕的Python程序比那个糟糕的Ruby程序慢”。比较最快的实现才有意义,而不是用相同的代码。我必须同时同意和反对。比较糟糕的程序确实没有帮助。但是,我不同意您应该比较最快的实现。我认为您应该比较设计最完善的实现。编译器编写者的工作是确保设计最完善的实现也是最快的,但如果不是这样,那么就不应该优化代码,而应该修复编译器。@Jörg W Mittag:是的,我完全同意你的观点。@Jörg W Mittag:不同的人可能会对哪种实现最快有不同的意见“设计最完善的实现”。问题不在于如何编写高效的fib()实现。问题在于为什么在Python中创建大型调用堆栈的成本更高(如果是这样的话)我的主要观点实际上应该是观察到的差异很小——这只是二的一个因素,这一点也不奇怪。再次阅读我的帖子,我认为其他人的评论更好,但我只想把它放在那里:)I li Python2.7 9.67 user 0.09 system 0:09.78 elapsed 99%CPU (0avgtext+0avgdata 16560maxresident)k 0inputs+0outputs (0major+1169minor)pagefaults 0swaps ruby 1.8.7 (2010-06-23 patchlevel 299) [x86_64-linux] 28.37 user 0.35 system 0:28.78 elapsed 99% CPU (0avgtext+0avgdata 9200maxresident)k 1896inputs+0outputs (9major+656minor)pagefaults 0swaps ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-linux] 6.21 user 0.08 system 0:06.36 elapsed 98% CPU (0avgtext+0avgdata 14160maxresident)k 4416inputs+0outputs (16major+953minor)pagefaults 0swaps 2.4.6 took 10.30 seconds 2.5.5 took 9.93 seconds 2.6.6 took 9.22 seconds 2.7 took 9.35 seconds 3.0.1 took 11.67 seconds 3.1.2 took 11.35 seconds 3.2a3+ (py3k:85895, Oct 29 2010, 01:41:57) [GCC 4.4.5] took 13.09 seconds 2.5.2 (77963, Oct 15 2010, 02:00:43) [PyPy 1.3.0] took 21.26 seconds 2.5.1 (Release_2_5_1:6813, Sep 26 2009, 13:47:54) [OpenJDK 64-Bit Server VM (Sun Microsystems Inc.)] took 8.81 seconds