为什么用 Python 解释器比 PyPy 更快地计算小斐波那契数列
Why calculating small fibonacci sequence with Python interpreter faster than 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 比 Python[=16= 快 60 倍]
PyPy: 0.1999509334564209
Python: 12.051937103271484
pypy JIT 需要一点时间来初始化,并且会更好地处理重复结果。用一个稍微不同的代码版本来说明:
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
除了其他答案:如果您的斐波那契示例是用 C、C#、Python 编写的,那么它的速度将 运行 大致相同,有或没有 JIT,或其他任何地方。那是因为斐波那契示例产生了指数级的大数字。几次迭代后,它一直在库内处理越来越大的整数,几乎 none 在库外。
当然,我们可以讨论为什么在这种或这种情况下它更快或更慢的细节,但这是在比较小的常量开销和所使用的长整数库的细节;跟语言关系不大。
我正在用 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 比 Python[=16= 快 60 倍]
PyPy: 0.1999509334564209
Python: 12.051937103271484
pypy JIT 需要一点时间来初始化,并且会更好地处理重复结果。用一个稍微不同的代码版本来说明:
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
除了其他答案:如果您的斐波那契示例是用 C、C#、Python 编写的,那么它的速度将 运行 大致相同,有或没有 JIT,或其他任何地方。那是因为斐波那契示例产生了指数级的大数字。几次迭代后,它一直在库内处理越来越大的整数,几乎 none 在库外。
当然,我们可以讨论为什么在这种或这种情况下它更快或更慢的细节,但这是在比较小的常量开销和所使用的长整数库的细节;跟语言关系不大。