cython numpy积累功能

And*_*nca 7 python performance numpy cython

我需要实现一个函数来汇总具有可变节长度的数组元素.所以,

a = np.arange(10)
section_lengths = np.array([3, 2, 4])
out = accumulate(a, section_lengths)
print out
array([  3.,   7.,  35.])
Run Code Online (Sandbox Code Playgroud)

我在cython这里尝试了一个实现:

https://gist.github.com/2784725

为了性能,我将比较numpysection_lengths完全相同的纯解决方案:

LEN = 10000
b = np.ones(LEN, dtype=np.int) * 2000
a = np.arange(np.sum(b), dtype=np.double)
out = np.zeros(LEN, dtype=np.double)

%timeit np.sum(a.reshape(-1,2000), axis=1)
10 loops, best of 3: 25.1 ms per loop

%timeit accumulate.accumulate(a, b, out)
10 loops, best of 3: 64.6 ms per loop
Run Code Online (Sandbox Code Playgroud)

你对改善表现有什么建议吗?

Jos*_*del 2

您可以尝试以下一些方法:

  • 除了@cython.boundscheck(False)编译器指令之外,还尝试添加@cython.wraparound(False)

  • 在您的setup.py脚本中,尝试添加一些优化标志:

    ext_modules = [Extension("accumulate", ["accumulate.pyx"], extra_compile_args=["-O3",])]

  • 查看生成的 .html 文件,cython -a accumulate.pyx看看是否有缺少静态类型或严重依赖 Python C-API 调用的部分:

    http://docs.cython.org/src/quickstart/cythonize.html#defining-where-to-add-types

  • return在方法末尾添加一条语句。目前,它正在您的紧密循环中进行一堆不必要的错误检查i_el += 1

  • 不确定它是否会有所作为,但我倾向于制作循环计数器而cdef unsigned int不仅仅是int

当不相等时,您还可以将代码与 numpy 进行比较section_lengths,因为它可能需要的不仅仅是简单的sum.