【问题标题】:Cython numpy array indexingCython numpy 数组索引
【发布时间】:2011-11-18 17:37:10
【问题描述】:

我正在尝试使用 cython 加速一些 python 代码,并且我正在使用 cython 的 -a 选项来查看可以改进的地方。我的理解是,在生成的 html 文件中,突出显示的行是调用 python 函数的行 - 对吗?

在下面的简单函数中,我使用缓冲区语法声明了 numpy 数组参数 arr。我认为这允许索引操作完全在 C 中进行,而无需调用 python 函数。但是,cython -a(0.15 版)突出显示了我设置arr 元素值的行,尽管不是我读取其中一个元素的行。为什么会这样?有没有更有效的方式访问 numpy 数组元素?

import numpy
cimport numpy

def foo(numpy.ndarray[double, ndim=1] arr not None):
    cdef int i
    cdef double elem
    for i in xrange(10):
      elem = arr[i]          #not highlighted
      arr[i] = 1.0 + elem    #highlighted

编辑:另外,mode 缓冲区参数如何与 numpy 交互?假设我没有更改默认的numpy.arrayorder 参数,那么使用mode='c' 总是安全的吗?这真的会对性能产生影响吗?

在 delnan 的评论后编辑:arr[i] += 1 也被突出显示(这就是为什么我首先将其拆分,以查看导致问题的操作部分)。如果我关闭边界检查以简化事情(这与突出显示的内容没有区别),生成的 c 代码是:

  /* "ct.pyx":11
 *   cdef int i
 *   cdef double elem
 *   for i in xrange(10):             # <<<<<<<<<<<<<<
 *     elem = arr[i]
 *     arr[i] = 1.0 + elem
 */
  for (__pyx_t_1 = 0; __pyx_t_1 < 10; __pyx_t_1+=1) {
    __pyx_v_i = __pyx_t_1;

    /* "ct.pyx":12
 *   cdef double elem
 *   for i in xrange(10):
 *     elem = arr[i]             # <<<<<<<<<<<<<<
 *     arr[i] = 1.0 + elem
 */
    __pyx_t_2 = __pyx_v_i;
    __pyx_v_elem = (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_arr.buf, __pyx_t_2, __pyx_bstride_0_arr));

    /* "ct.pyx":13
 *   for i in xrange(10):
 *     elem = arr[i]
 *     arr[i] = 1.0 + elem             # <<<<<<<<<<<<<<
 */
    __pyx_t_3 = __pyx_v_i;
    *__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_arr.buf, __pyx_t_3, __pyx_bstride_0_arr) = (1.0 + __pyx_v_elem);
  }

【问题讨论】:

  • arr[i] += 1 是否突出显示?另外,我相信您可以直接在cython -a 生成的 HTML 文档中查看为该特定行生成的代码,也许有助于了解该行发生了哪些 Python API 调用。

标签: python arrays indexing numpy cython


【解决方案1】:

答案是荧光笔愚弄了读者。 我编译了你的代码,高亮下生成的指令是需要的 处理错误情况和返回值,它们与数组赋值无关。

确实,如果您将代码更改为:

def foo(numpy.ndarray[double, ndim=1] arr not None):
    cdef int i
    cdef double elem
    for i in xrange(10):
      elem = arr[i]
      arr[i] = 1.0 + elem
    return # + add this

突出显示在最后一行,而不是在作业中。

您可以使用@cython.boundscheck 进一步加快您的代码速度:

import numpy
cimport numpy
cimport cython

@cython.boundscheck(False)
def foo(numpy.ndarray[double, ndim=1] arr not None):
    cdef int i
    cdef double elem
    for i in xrange(10):
      elem = arr[i]
      arr[i] = 1.0 + elem
    return 

【讨论】:

  • 提供的 C 代码显示没有绑定检查,没有环绕索引计算。所以我假设提问者在他的 setup.py 中停用了它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-23
  • 1970-01-01
  • 2022-06-30
  • 2012-03-17
  • 1970-01-01
相关资源
最近更新 更多