在cython中,如何在环路中获得更好的速度性能?

2024-04-29 03:13:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我用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

我用来测试以下代码的性能:

^{pr2}$

但是我没有发现任何明显的改进。我还没有用打字的记忆视图。有谁能提出有用的解决方案来提高速度或帮助我用类型化内存视图重写代码吗?在


Tags: 代码inboardforsizerange性能cython
2条回答

你说得对,如果不向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)

但还是快了两倍。通过添加类型,例如

^{pr2}$

速度更快(几乎快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)来获得更精确的计时。在


请注意,您还可以使用来获得很好的加速效果,而无需任何额外的静态类型:

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)

我实现了一个运行速度更快的函数。我简单地将black_rave和{}声明为memoryviews,并将它们放入返回值中:

cdef tuple cy_playout1(int[:, :] board, int N):
    cell_size = int((size ** 2) / 2) + 10
    cdef int[:, :] black_rave = np.empty([cell_size, 2], dtype=np.int32)
    cdef int[:, :] white_rave = np.empty([cell_size, 2], dtype=np.int32)

    cdef int i, j, x, y, h
    i, j = 0, 0
    cdef int M,L
    M = board.shape[0]
    L = board.shape[1]
    for h in range(N):
        for x in range(M):
            for y in range(L):
                if board[x,y] == 0:
                    black_rave[i][0], black_rave[i][1] = x, y
                    i += 1
                elif board[x,y] == 1:
                    white_rave[j][0], white_rave[j][1] = x, y
                    j += 1
        i = 0
        j = 0

    return black_rave[:i], white_rave[:j]

以下是速度测试结果:

^{pr2}$

相关问题 更多 >