Что-то не так с этим кодом на python, почему он работает так медленно по сравнению с ruby? - PullRequest
4 голосов
/ 28 октября 2010

Мне было интересно сравнить скорость в рубинах с питоном, поэтому я взял простейший рекурсивный расчет, а именно вывел последовательность Фибоначчи.

Это код 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 ​​

#!/usr/bin/ruby

def fib(n)
    if n == 0
        return 0
    elsif n == 1
        return 1
    else
        fib(n-1)+fib(n-2)
    end
end 

i = 0 
while (i < 35)
    puts fib(i)
    i = i + 1 
end

за несколько прогонов, время сообщает об этом среднем

real    0m4.782s 
user    0m4.763s 
sys     0m0.010s

, то есть для ruby, теперь python2.7 дает

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

Что такое сделка?

Ответы [ 5 ]

7 голосов
/ 29 октября 2010

Причиной этих издержек является эффективность рекурсии python.См. эту статью для более подробной информации.Вышеупомянутые решения, которые решают это итеративно, лучше для python, так как они не несут рекурсию служебных вызовов вызова.Мое предположение о ruby ​​заключается в том, что он явно оптимизирует код, а python - нет.Опять же, в этой статье подробно рассказывается об этом с использованием почти идентичной функции fib.

2 голосов
/ 29 октября 2010

Вот еще несколько цифр для сравнения:

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

Python в три раза быстрее , чем ruby1.8, и на 30% медленнее, чем ruby1.9.1 для предоставленного кода.

Другие версии 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 голосов
/ 28 октября 2010

Ваш метод вычисления первых 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, а также самый универсальный.

2 голосов
/ 28 октября 2010

Мне было интересно сравнить скорость рубина с питоном

Микробенчмарки - действительно плохой способ сравнения языков, особенно до того, как вы освоили оба.Если вам нужен эталон, который имеет какое-то значение для реального мира, вам нужно приложить немало усилий - или вы Google для "языковой перестрелки"

Вот лучшее сравнение Python и Ruby

2 голосов
/ 28 октября 2010

Так что для этого кода Python чуть более чем в два раза медленнее, чем Ruby.Вероятно, для других кодов Python будет быстрее, чем Ruby.

Ваша реализация fib () имеет экспоненциальное время выполнения.Этого легко избежать, используя петлю.Пример Python:

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