#python #python-3.x #performance #pypy
Вопрос:
Я делал некоторые вычисления фибоначчи с помощью PyPy, сначала я начал с больших чисел, PyPy был немного быстрее, но с небольшими числами он дает почти такую же производительность, а в некоторых случаях обычный интерпретатор намного быстрее, чем pypy. Есть ли конкретная причина, почему?
from time import time
def fibonacci(n):
a, b = 0, 1
for i in range(0, n):
a, b = b, a b
return a
start = time()
result = fibonacci(5000)
end = time()
print(end-start)
С небольшим числом, таким как 5000, Python на самом деле быстрее, чем PyPy;
Python: 0.0006256103515625
PyPy: 0.0016071796417236328
Когда дело доходит до немного большего числа, такого как 1.000.000, PyPy работает быстрее, чем Python
PyPy: 8.567905902862549
Python: 9.79963207244873
Но когда дело доходит до другого расчета, например:
def sum_in_range(a,b):
c = 0
for i in range(1, a):
for j in range(1, b):
c = i j
return c
start = time()
result = sum_in_range(100000,100000)
end = time()
print(end-start)
PyPy в 60 раз быстрее Python
PyPy: 0.1999509334564209
Python: 12.051937103271484
Комментарии:
1. Из данных по эффективности страницу ( pypy.org/performance.html ): «[…] JIT-компилятором как известно, не работает на […] очень короткий-запуск скриптов: как правило, если что-то работает ниже 0,2 с JIT-компилятором нет шансов» — ваш время выполнения слишком короткое данных по Джит, чтобы превзойти обычные с CPython
2. @Carcigenicate тоже пытался это
timeit('fibonacci(100)','from __main__ import fibonacci')
сделать, результат был почти таким же3. @UnholySheep, но и с таким числом, как 500 000, python все равно выигрывает… оба они заканчиваются более чем за 2 секунды.
Ответ №1:
В дополнение к другим ответам: ваш пример фибоначчи работал бы примерно с той же скоростью, если бы он был написан на C, C#, на Python с JIT или без него, или где-либо еще. Это потому, что пример Фибоначчи дает экспоненциально большие числа. После нескольких итераций он тратит все время внутри библиотеки, обрабатывая все большие целые числа, и почти ничего за ее пределами.
Конечно, мы можем обсудить более тонкие моменты, почему это немного быстрее или медленнее в том или ином случае, но это сравнение небольших постоянных накладных расходов и деталей используемых библиотек с длинными целыми числами; это имеет мало общего с языком.
Ответ №2:
Для инициализации JIT pypy требуется немного времени, и он будет лучше работать с повторными результатами. Чтобы проиллюстрировать немного другую версию кода:
from __future__ import print_function
import sys
from datetime import datetime
def fibonacci(n):
a, b = 0, 1
for i in range(0, n):
a, b = b, a b
return a
n = int(sys.argv[1])
runs = int(sys.argv[2])
durations = []
for i in range(runs):
start = datetime.now()
fibonacci(int(n))
durations.append(datetime.now() - start)
durations.sort()
print('min:', durations[0])
print('median:', durations[int(runs / 2)])
print('max:', durations[-1])
И запуск его на нескольких версиях Python:
# python2 --version
Python 2.7.18rc1
# python2 fib.py 5000 1000
min: 0:00:00.000303
median: 0:00:00.000307
max: 0:00:00.001273
# python2 fib.py 1000000 5
min: 0:00:05.711701
median: 0:00:05.782151
max: 0:00:05.850577
# python3 --version
Python 3.8.2
# python3 fib.py 5000 1000
min: 0:00:00.000305
median: 0:00:00.000309
max: 0:00:00.001254
# python3 fib.py 1000000 5
min: 0:00:05.796954
median: 0:00:05.825557
max: 0:00:05.841489
# pypy --version
Python 2.7.13 (7.3.1 dfsg-2, Apr 21 2020, 05:05:41)
[PyPy 7.3.1 with GCC 9.3.0]
# pypy fib.py 5000 1000
min: 0:00:00.000160
median: 0:00:00.000179
max: 0:00:00.002456
# pypy fib.py 1000000 5
min: 0:00:04.314290
median: 0:00:04.405727
max: 0:00:04.453215