我已经开始了一个Python项目,它主要由循环组成。几天前,我读到了有关 cython 的内容,它可以帮助您通过静态类型获得更快的代码。 我开发了这两个函数来检查性能(一个在 python 中,另一个在 cython 中):
import numpy as np
from time import clock
size = 11
board = np.random.randint(2, size=(size, size))
def py_playout(board, N):
black_rave = []
white_rave = []
for i in range(N):
for x in range(board.shape[0]):
for y in range(board.shape[1]):
if board[(x,y)] == 0:
black_rave.append((x,y))
else:
white_rave.append((x,y))
return black_rave, white_rave
cdef cy_playout(board, int N):
cdef list white_rave = [], black_rave = []
cdef int M = board.shape[0], L = board.shape[1]
cdef int i=0, x=0, y=0
for i in range(N):
for x in range(M):
for y in range(L):
if board[(x,y)] == 0:
black_rave.append((x,y))
else:
white_rave.append((x,y))
return black_rave, white_rave
我最终使用了下面的代码来测试性能:
t1 = clock()
a = playout(board, 1000)
t2 = clock()
b = playout1(board, 1000)
t3 = clock()
py = t2 - t1
cy = t3 - t2
print('cy is %a times better than py'% str(py / cy))
但是我没有发现任何明显的改进。我还没有使用过 Typed-Memoryviews。有人可以建议有用的解决方案来提高速度或帮助我使用 typed-memoryview 重写代码吗?
最佳答案
你是对的,如果不向 cython 函数中的 board
参数添加类型,加速并不会那么快:
%timeit py_playout(board, 1000)
# 321 ms ± 19.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit cy_playout(board, 1000)
# 186 ms ± 541 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
但速度仍然快了两倍。通过添加类型,例如
cdef cy_playout(int[:, :] board, int N):
# ...
# or if you want explicit types:
# cimport numpy as np
# cdef cy_playout(np.int64_t[:, :] board, int N): # or np.int32_t
速度快得多(几乎快了 10 倍):
%timeit cy_playout(board, 1000)
# 38.7 ms ± 1.84 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
我还使用了 timeit
(好吧,IPython 魔法 %timeit
)来获得更准确的计时。
请注意,您还可以使用 numba无需任何额外的静态类型即可实现巨大的加速:
import numba as nb
nb_playout = nb.njit(py_playout) # Just decorated your python function
%timeit nb_playout(board, 1000)
# 37.5 ms ± 154 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
关于python - 如何在 cython 中实现更好的循环速度性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45446052/