Почему моя версия Python медленнее, чем моя версия Perl?
Я был парком Perl более 10 лет, но друг убедил меня попробовать Python и сказал мне, насколько он быстрее, чем Perl. Так что для пинков я портировал приложение, написанное в Perl на Python, и обнаружил, что он работает примерно на 3 раза медленнее. Первоначально мой друг сказал мне, что я, должно быть, сделал это неправильно, поэтому я переписал и реорганизовал, пока я не смог переписать и не рефакторировать больше и... он все еще намного медленнее. Поэтому я сделал простой тест:
i = 0
j = 0
while (i < 100000000):
i = i + 1
j = j + 1
print j
$time python python.py
100000000
real 0m48.100s
пользователя 0m45.633s
sys 0m0.043s
my $i = 0;
my $j = 0;
while ($i < 100000000) {
++$i; # also tested $i = $i + 1 to be fair, same result
++$j;
}
print $j;
$time perl perl.pl
100000000
real 0m24.757s
пользователя 0m22.341s
sys 0m0.029s
В два раза медленнее, что, похоже, не отражает каких-либо тестов, которые я видел... это проблема с моей установкой или Python действительно намного медленнее, чем Perl?
Ответы
Ответ 1
Ответ на выбор nit заключается в том, что вы должны сравнить его с идиоматическим Python:
У Python есть странное свойство, что более быстрый код более высокого уровня имеет тенденцию быть самым быстрым: -)
Но реальный ответ заключается в том, что ваш "микро-бенчмарк" не имеет смысла.
Реальный вопрос о скорости языка: какова производительность среднего реального приложения? Чтобы это знать, вы должны учитывать:
-
Типичное сочетание операций в сложном коде.
Ваш код не содержит никаких структур данных, вызовов функций или операций ООП.
-
Достаточно большая база кода, чтобы ощущать эффекты кеша - многие оптимизаторы интерпретатора используют торговую память для скорости, которая не измеряется справедливо ни одним крошечным эталоном.
-
Оптимизация возможности: после вы пишете свой код, если он не достаточно быстрый,
насколько быстрее вы можете легко это сделать?
например. насколько трудно разгружать тяжелый подъем на эффективные C-либрики?
Тесты PyPy и Octane являются хорошие примеры того, как выглядят реалистичные языковые тесты скорости.
Если вы хотите поговорить с хрустом числа, Python IS на удивление популярен среди ученых.
Они любят его для простого псевдоматного синтаксиса и короткой кривой обучения, но также для отличной библиотеки numpy для хруста массива и простоты обертывания другого существующего кода C.
И затем есть Psyco JIT, который, вероятно, запустит ваш пример с игрушкой менее 1 секунды, но я не могу проверить его сейчас потому что он работает только на 32-битном x86.
EDIT: В настоящее время пропустите Psyco и используйте PyPy, где кросс-платформа активно улучшает JIT.
Ответ 2
Все это микро-бенчмаркинг может стать немного глупым!
Например, просто переключение на for
в Python и Perl обеспечивает высокую скорость. Первоначальный пример Perl был бы вдвое быстрее, если бы использовался for
:
my $j = 0;
for my $i (1..100000000) {
++$j;
}
print $j;
И я могу немного сбрить с этим:
++$j for 1..100000000;
print $j;
И, становясь еще глуже, мы можем получить его до 1 секунды здесь; -)
print {STDOUT} (1..10000000)[-1];
/I3az/
ref: используется Perl 5.10.1.
Ответ 3
Python не особенно быстро работает с числовыми вычислениями, и я уверен, что он медленнее, чем perl, когда дело доходит до обработки текста.
Поскольку вы опытная рука Perl, я не знаю, относится ли это к вам, но программы Python в долгосрочной перспективе, как правило, более удобны в обслуживании и быстрее развиваются. В большинстве случаев скорость "достаточна", и у вас есть гибкость, чтобы спуститься на C, когда вам действительно нужно повысить производительность.
Update
Хорошо. Я просто создал большой файл (1 ГБ) со случайными данными в нем (в основном ascii) и разбил его на строки равной длины. Это должно было имитировать файл журнала.
Затем я запускал простые программы perl и python, которые ищут файл строки за строкой для существующего шаблона.
С Python 2.6.2 результаты были
real 0m18.364s
user 0m9.209s
sys 0m0.956s
и с Perl 5.10.0
real 0m17.639s
user 0m5.692s
sys 0m0.844s
Программы выглядят следующим образом (пожалуйста, дайте мне знать, если я делаю что-то глупое)
import re
regexp = re.compile("p06c")
def search():
with open("/home/arif/f") as f:
for i in f:
if regexp.search(i):
print "Found : %s"%i
search()
и
sub search() {
open FOO,"/home/arif/f" or die $!;
while (<FOO>) {
print "Found : $_\n" if /p06c/o;
}
}
search();
Результаты довольно близки, и их настройка так или иначе не сильно изменяет результаты. Я не знаю, является ли это истинным эталоном, но я думаю, что я бы поискал файлы журналов на двух языках, поэтому я исправляю относительные характеристики.
Спасибо Крису.
Ответ 4
Python работает очень быстро, если вы используете правильный синтаксис языка python. Он примерно описан как pythonic".
Если вы реструктурируете свой код, как это, он будет работать как минимум в два раза быстрее (ну, это на моей машине):
j = 0
for i in range(10000000):
j = j + 1
print j
Всякий раз, когда вы используете время на python, вы должны проверить, можете ли вы также использовать "для X в диапазоне()".
Ответ 5
В OP, в Python этот фрагмент кода:
j = 0
for i in range(10000000):
j = j + 1
print j
совпадает с
print range(10000001)[-1]
который на моей машине
$ time python test.py
10000000
real 0m1.138s
user 0m0.761s
sys 0m0.357s
пробегает приблизительно 1 с. range() (или xrange) является внутренним для Python и "внутренне", он уже может генерировать последовательность чисел для вас. Поэтому вам не нужно создавать свои собственные итерации, используя собственный цикл. Теперь вы идете и находите эквивалент Perl, который может работать в течение 1 с для получения того же результата.
Ответ 6
Python поддерживает глобальные переменные в словаре. Поэтому каждый раз, когда есть задание, интерпретатор выполняет поиск в словаре модулей, что несколько дорого, и именно поэтому вы нашли ваш пример настолько медленным.
Чтобы повысить производительность, вы должны использовать локальное распределение, например, создание функции. Интерпретатор Python хранит локальные переменные в массиве с гораздо более быстрым доступом.
Однако следует отметить, что это деталь реализации CPython; Я подозреваю, что IronPython, например, приведет к совершенно другому результату.
Наконец, для получения дополнительной информации по этой теме я предлагаю вам интересное эссе из GvR, посвященное оптимизации в Python: Шаблоны Python - Анекдот оптимизации.
Ответ 7
python медленнее, чем perl. Это может быть быстрее развиваться, но оно не выполняется быстрее. Здесь приведен один критерий http://xodian.net/serendipity/index.php?/archives/27-Benchmark-PHP-vs.-Python-vs.-Perl-vs.-Ruby.html -edit- страшный тест, но это, по крайней мере, реальный бенчмарк с числами, а не догадываться. Для плохого нет источника или теста другого, а затем цикла.
Ответ 8
Я не обновляюсь на всех с Python, но моя первая идея об этом контроле была разницей между числами Perl и Python. В Perl у нас есть числа. Они не являются объектами, и их точность ограничена размерами, налагаемыми архитектурой. В Python у нас есть объекты с произвольной точностью. Для небольших чисел (те, которые соответствуют 32-битным), я ожидаю, что Perl будет быстрее. Если мы перейдем к целочисленному размеру архитектуры, Perl script даже не будет работать без какой-либо модификации.
Я вижу похожие результаты для исходного теста на моем MacBook Air (32-разрядный), используя Perl 5.10.1, который я скомпилировал сам и Python 2.5.1, который пришел с Leopard:
Однако я добавил произвольную точность в программу Perl с bignum
use bignum;
Теперь мне интересно, закончится ли версия Perl.:) Я опубликую некоторые результаты, когда закончится, но похоже, что это будет различие в величине порядка.
Некоторые из вас, возможно, видели мой вопрос о Какие пять вещей вы ненавидите в своем любимом языке?. Perl-номера по умолчанию - одна из вещей, которые я ненавижу. Я никогда не должен думать об этом, и это не должно быть медленным. В Perl я проигрываю на обоих. Обратите внимание, однако, что если бы мне нужна числовая обработка в Perl, я мог бы использовать PDL.
Ответ 9
Python действительно намного медленнее, чем Perl?
Посмотрите на Компьютерные игры Benchmarks Game - "Сравните производительность ≈30 языков программирования, используя ≈12 ошибочных тестов и ≈1100 программ".
Это всего лишь крошечные тестовые программы, но они по-прежнему намного больше, чем фрагмент кода, который вы приурочили -
http://shootout.alioth.debian.org/u32/python.php