提高cython数组索引速度

Max*_*ger 4 python arrays numpy cython

我有一个非常简单的功能,我需要加快速度.基本上我有一个16位数字的大数组,其中有一些洞.(大约10%)我需要遍历数组,找到连续有2 0的区域,然后用前一个和下一个元素的平均值填充它们.这在C中只需要几毫秒,但Python正在变得更糟.

我已经从普通的python数组转换为numpy数组,然后使用cython编译我的代码,但我仍然远离我的目标.我希望有更多经验的人可以看看我在做什么并给我一些反馈.

我的常规python代码如下所示:

self.rawData = numpy.fromfile(ql, numpy.uint16, 50000)
[snip]
def fixZeroes(self):
    for x in range(2,len(self.rawData)):
        if self.rawData[x] == 0 and self.rawData[x-1] == 0:
            self.rawData[x] = (self.rawData[x-2] + self.rawData[x+2]) / 2
            self.rawData[x-1] = (self.rawData[x-3] + self.rawData[x+1]) /2
Run Code Online (Sandbox Code Playgroud)

我的Cython代码看起来非常相似:

import numpy as np
cimport numpy as np
DTYPE = np.uint16
ctypedef np.uint16_t DTYPE_t

@cython.boundscheck(False)
def fix_zeroes(np.ndarray[DTYPE_t, ndim=1] raw):
    assert raw.dtype == DTYPE
    cdef int len = 50000

    for x in range(2,len):
        if raw[x] == 0 and raw[x-1] == 0:
            raw[x] = (raw[x-2] + raw[x+2]) / 2
        raw[x-1] = (raw[x-3] + raw[x+1]) /2
    return raw
Run Code Online (Sandbox Code Playgroud)

当我运行此代码时,性能仍然比我想要的慢:

启动cython零修复

完成:0:00:36.983681

启动python零修复

完成:0:00:41.434476

我真的认为我一定做错了.我见过的大多数文章都谈到了numpy和cython增加的巨大性能提升,但我几乎没有打破10%.

Sau*_*tro 6

您应该声明x用于索引raw数组的变量:

cdef int x
Run Code Online (Sandbox Code Playgroud)

您还可以使用通常可以提高性能的其他指令:

@cython.wraparound(False)
@cython.cdivision(True)
@cython.nonecheck(False)
Run Code Online (Sandbox Code Playgroud)

  • 哇!是的,那就是问题所在.我从36.9秒到.0072秒.我称之为胜利. (2认同)
  • @MaxwellBottiger太棒了,请记住这些指令!你将来可能面临的另一件事是用`x*x`替换`x**2`,因为第一个将在函数调用中转换,就像`pow(x,2)` (2认同)