我们可以让 Python for 循环更快。
发帖人的问题是,为什么 Python“for 循环”相对于 C# 和 JavaScript 如此缓慢。提出一种减少“for 循环”需求的不同算法并不能解决这个问题(特别是因为 C# 和 JavaScript 版本使用修改后的算法也会更快)。一般来说,编程语言使用类似的算法进行比较,它们的区别在于语言特性使它们能够在任务中表现出色——https ://benchmarksgame-https: //benchmarksgame-team.pages.debian.net/benchmarksgame/index
。 html
在这种情况下,任务是使用 Python 语言功能更快地搜索超过十亿个数字(三个嵌套 for 循环的大小)?
尝试了两种方法来加速代码:Cython 和 Numba(分别)。
设置:
- Jupyter 笔记本
- Python 3.5.2 操作系统
- Windows 10 64 位
- 处理器 i7
结果:
- Python 3.5.2 => 387.356 秒
- Cython => 117.223 秒
- Cython(改进)=> 0.63 秒(使用@CodeSurgeon 建议)
- Numba => 0.5 秒
Numba 版本堪比海报的 JavaScript 和 C# 时代。Numba 使用相同的“次优”算法比纯 Python 提供了 774 的加速。请注意,所有三个实现都使用基本相同的代码,如下所示。
- Python 3.5.2 代码
import time
def solve():
for c in range(1000, 0, -1):
for a in range(1000, 0, -1):
for b in range(1000, 0, -1):
if (a*a)+(b*b)==(c*c):
if a+b+c == 1000:
return a*b*c
to = time.time()
print('I have found it {}'.format(solve()))
print("Elapsed Time\n", time.time()- t0)
Python 3.5.2 输出
I have found it 31875000
Elapsed Time
387.3550021648407
- Cython 代码(参见https://ipython-books.github.io/55-accelerating-python-code-with-cython/)
%load_ext cython
%%cython -a
import time
def solve():
for c in range(1000, 0, -1):
for a in range(1000, 0, -1):
for b in range(1000, 0, -1):
if (a*a)+(b*b)==(c*c):
if a+b+c == 1000:
return a*b*c
t0 = time.time()
print('I have found it {}'.format(solve()))
print("Elapsed Time\n", time.time()- t0)
赛通输出
I have found it 31875000
('Elapsed Time\n', 117.22299981117249)
Cython(与 Cdef https://buildmedia.readthedocs.org/media/pdf/notes-on-cython/latest/notes-on-cython.pdf)
%%cython -a
进口时间
cdef int solve(): cdef int a, b, c
for c in range(1000, 0, -1):
for a in range(1000, 0, -1):
for b in range(1000, 0, -1):
if (a*a)+(b*b)==(c*c):
if a+b+c == 1000:
return a*b*c
t0 = time.time() print('我找到了{}'.format(solve())) print("Elapsed Time\n", time.time()- t0)
输出(使用 Cdef 的 Cython)
I have found it 31875000
('Elapsed Time\n', 0.6340005397796631)
- Numba 代码(参见https://numba.pydata.org/)
import time
from numba import jit
@jit(nopython=True) # only need to add Numba decorator to get speed up
def solve():
for c in range(1000, 0, -1):
for a in range(1000, 0, -1):
for b in range(1000, 0, -1):
if (a*a)+(b*b)==(c*c):
if a+b+c == 1000:
return a*b*c
t0 = time.time()
print('I have found it {}'.format(solve()))
print("Elapsed Time\n", time.time()- t0)
Numba 输出
I have found it 31875000
Elapsed Time
0.5209996700286865