Почему Python медленнее, чем Ruby, даже с этим очень простым «тестом»? - PullRequest
2 голосов
/ 01 ноября 2010

См. Что-то не так с этим кодом Python, почему он работает так медленно по сравнению с ruby? для моей предыдущей попытки понять различия между python и ruby.

Как указал igouy, рассуждение о том, что python медленнее, может быть чем-то иным, нежели из-за рекурсивных вызовов функций (в стеке).

Я сделал это

#!/usr/bin/python2.7
i = 0
a = 0
while i < 6553500:
    i += 1
    if i != 6553500:
       a = i 
    else:
        print "o" 
print a 

В ruby ​​это

#!/usr/bin/ruby
i = 0
a = 0
while i < 6553500
    i += 1
    if i != 6553500
       a = i 
    else
        print "o"
    end
end   
print a

Python 3.1.2 (r312: 79147, 4 октября 2010, 12:45:09)[GCC 4.5.1] в linux2

time python pytest.py o

6553499

real 0m3.637s

пользователь 0m3.586s

ruby ​​1.9.2p0 (версия 2010-08-18 29036) [x86_64-linux] time ruby ​​rutest.rb

o6553499

реальный 0m0,618s

пользователь0m0.610s

Повышение цикла дает более высокие различия.Добавляя 0, рубин завершается через 7 секунд, а python работает в течение 40 секунд.

Это выполняется на процессоре Intel® Core iMM M 620 @ 2,67 ГГц с памятью 4 ГБ

Почему это так?

Ответы [ 4 ]

16 голосов
/ 01 ноября 2010

Прежде всего, обратите внимание, что версия Python, которую вы показываете, неверна: вы запускаете этот код в Python 2.7, а не 3.1 (это даже не допустимый код Python3).(К сведению, Python 3 обычно медленнее, чем 2.)

Тем не менее, в тесте Python есть критическая проблема: вы пишете его как глобальный код.Вы должны написать это как функцию.При правильной записи он работает примерно в два раза быстрее, как в Python 2, так и в 3:

def main():
    i = 0
    a = 0
    while i < 6553500:
        i += 1
        if i != 6553500:
           a = i
        else:
            print("o")
    print(a)

if __name__ == "__main__":
    main()

Когда вы пишете код глобально, у вас нет локальных элементов;все ваши переменные являются глобальными переменными.Локальные данные намного быстрее, чем глобальные в Python, потому что глобальные значения хранятся в dict.К локальным ссылкам может обращаться виртуальная машина напрямую по индексу, поэтому поиск хеш-таблиц не требуется.

Также обратите внимание, что это такой простой тест, который вы действительно делаете, сравнивая несколько произвольных операций с байт-кодом.

2 голосов
/ 01 ноября 2010

Почему это так?

Цикл Python (пока) не быстр для обработки динамических типов.в таком случае он теряет преимущество.

но cython стал спасением
версия чистого Python ниже заимствована из ответа Гленна Мейнарда (без печати)
версия Cython очень проста на этом основании, она достаточно проста для чтения новым программистом Python:

def main():
    cdef int i = 0
    cdef int a = 0
    while i < 6553500:
        i += 1
        if i != 6553500:
            a = i
        else:
            pass  # print "0"
    return a

if __name__ == "__main__":
    print main()

на моем компьютере, для версии Python требуется 2,5 с, для версии Cython необходимо 5,5 мс:

In [1]: import pyximport

In [2]: pyximport.install()

In [3]: import spam  # pure python version

In [4]: timeit spam.main()
1 loops, best of 3: 2.41 s per loop

In [5]: import eggs  # cython version

In [6]: timeit eggs.main()
100 loops, best of 3: 5.51 ms per loop

обновление: как отметил Гленн Мейнард в комментарии, а i Я тестирую реализацию xrange.
spam.py совпадает с версией Гленна Мейнарда.Код foo.py:

def main():
    for i in xrange(6553500):
        pass
    a = i
    return a

if __name__ == "__main__":
    print main()
~/code/note$ time python2.7 spam.py  # Glenn Maynard's while version
6553499

real    0m2.128s
user    0m2.080s
sys     0m0.044s
:~/code/note$ time python2.7 foo.py  # xrange version, as Glenn Maynard point out in comment
6553499

real    0m0.618s
user    0m0.604s
sys     0m0.016s
1 голос
/ 01 ноября 2010

На ноутбуке моего друга (Windows7 64 бит, python 2.6, 3 ГБ ОЗУ) python занимает всего около 1 секунды для 6553500 и 10 секунд для 65535000 ввода. Интересно, почему твой компьютер занимает так много времени. Это также сбрасывает некоторое время на больших входных данных, когда я вместо этого использую xrange и локальные переменные.

Я не могу комментировать Ruby, поскольку он не установлен на этом компьютере.

0 голосов
/ 01 ноября 2010

Это слишком простой тест.Возможно, в таких вещах Ruby работает быстрее.Но Python использует преимущества, когда вам нужно работать с более сложными типами данных и их методами.В Python реализовано гораздо больше «способов сделать это», и вы должны выбрать тот, который является самым простым и достаточным.Ruby работает с более абстрактными объектами и требует меньше знаний.Но когда в одной и той же задаче в Python возможно углубиться в его руководства и найти все больше и больше комбинаций типов и методов / функций, можно со временем сделать программу намного быстрее, чем Ruby.

Ruby проще и легче писать, если вы просто хотите получить результат, а не производительность.Но чем сложнее ваша задача, тем больше преимуществ у Python в производительности после нескольких часов оптимизации.

UPD: хотя в Ruby и Python много общего, у перфомасы и высокого уровня обратная пропорциональность.

...