在处理Numpy ndarray时,使用Cython提高速度

时间:2017-06-15 19:17:22

标签: python numpy cython

我在根据第i和第j个索引的总和是偶数还是奇数来改变numpy ndarray时测试Cython性能。与Python相比,Cython速度仅提高了80%,这在速度上有点平庸。我此刻已经没想完了。有什么建议?

@Python:

def even_odd_function(matrix):

    dim = matrix.shape[1]

    for i in range(dim):
        for j in range(dim):
            if (i + j) % 2 == 0:
                matrix[i, j] = matrix[i, j] ** 2
            else:
                matrix[i, j] = matrix[i, j] * -1

    return matrix

@Cython:

%%cython

import numpy as np
cimport numpy as np
cimport cython

DTYPE = np.int
ctypedef np.int DTYPE_t

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
def even_odd_function7(np.ndarray matrix):

    cdef int dim = matrix.shape[1]
    cdef int i
    cdef int j

    for i in range(dim):
        for j in range(dim):
            if (i + j) % 2 == 0:
                matrix[i, j] = matrix[i, j] * matrix[i, j]
            else:
                matrix[i, j] = matrix[i, j] * -1

    return matrix

以下是突出显示的行:  enter image description here

1 个答案:

答案 0 :(得分:4)

您需要为主要加速注释数组的类型。

import numpy as np
cimport numpy as np
cimport cython

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
def even_odd_function8(np.ndarray[np.float64_t, ndim=2] matrix):

    cdef int dim = matrix.shape[1]
    cdef int i
    cdef int j

    for i in range(dim):
        for j in range(dim):
            if (i + j) % 2 == 0:
                matrix[i, j] = matrix[i, j] * matrix[i, j]
            else:
                matrix[i, j] = matrix[i, j] * -1

    return matrix

In [20]: arr = np.random.randn(1000, 1000)

In [21]: %timeit even_odd_function(arr)
1 loop, best of 3: 636 ms per loop

In [22]: %timeit even_odd_function7(arr)
1 loop, best of 3: 480 ms per loop

In [24]: %timeit even_odd_function8(arr)
1000 loops, best of 3: 1.61 ms per loop

很大程度上是一种风格,但我更喜欢新的类型化的memoryview语法,它会做同样的事情。

def even_odd_function(np.float64_t[:,:] matrix)