【问题标题】:Improve cython array indexing speed提高 cython 数组索引速度
【发布时间】:2014-05-08 18:58:57
【问题描述】:

我有一个非常简单的功能,我需要加快速度。本质上,我有一大堆 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

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

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

开始 cython 零修复

完成:0:00:36.983681

启动 python 零修复

完成:0:00:41.434476

我真的认为我一定做错了什么。我看过的大多数文章都谈到了 numpy 和 cython 的巨大性能提升,但我几乎没有突破 10%。

【问题讨论】:

  • This takes only a few milliseconds in C。你有C函数吗?如果是这样,只需将其直接包装在 Cython 中并从您的 Python 程序中调用它。
  • @ThaneBrimhall 使用 Cython 以及所有增强指令和类型声明应该非常接近 C
  • @ThaneBrimhall - 好点。我有一个 C 函数,但它是一团糟。我需要重写算法,这是无论如何的一部分,所以这就是它被移植到 python 的原因。不过我确实喜欢你的建议。
  • @SaulloCastro 是的,我知道。但是我很懒,如果我已经完成了一些事情,我通常只是重复使用它。 ;)

标签: python arrays numpy cython


【解决方案1】:

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

cdef int x

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

@cython.wraparound(False)
@cython.cdivision(True)
@cython.nonecheck(False)

【讨论】:

  • 哇!是的,这就是问题所在。我从 36.9 秒到 0.0072 秒。我称之为胜利。
  • @MaxwellBottiger 太好了,请记住这些指令!您将来可能面临的另一件事是将x**2替换为x*x,因为第一个将在函数调用中进行转换,例如pow(x, 2)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-18
  • 2013-03-18
相关资源
最近更新 更多