Cython:从类型化的memoryview数组中读取值的最快方法是什么?

这些年来,我在cython中制定了许多例行程序,并对性能相对满意,直到周五的一位同事指出我的速度只有17倍。我曾以为加速比要大得多。因此,我使用cython -a program.pyx应用程序查看了生成的代码。 Here is a link to the report。我倾向于在进行非线性数学运算的地方制作循环,例如在while循环中:

cdef double simps(double[:] integrand,double[:] r):
        cdef int n = len(integrand)
        cdef int m = (n-1)/2
        cdef double s = 0.0
        cdef int i = 0
        while (i<m):
            s += (r[2*(i+1)] - r[2*i])*(integrand[2*i] + 4.0*integrand[2*i + 1] + integrand[2*i+2])
            i += 1
        return s/6.

下面的一行似乎需要很长时间才能评估。

s += (r[2*(i+1)] - r[2*i])*(integrand[2*i] + 4.0*integrand[2*i + 1] + integrand[2*i+2])

原因是所生成的代码对此类型进行了大量检查:

__pyx_t_4 = (2 * (__pyx_v_i + 1));
__pyx_t_5 = -1;
if (__pyx_t_4 < 0) {
  __pyx_t_4 += __pyx_v_r.shape[0];
  if (unlikely(__pyx_t_4 < 0)) __pyx_t_5 = 0;
} else if (unlikely(__pyx_t_4 >= __pyx_v_r.shape[0])) __pyx_t_5 = 0;
if (unlikely(__pyx_t_5 != -1)) {
  __Pyx_RaiseBufferIndexError(__pyx_t_5);
  {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
}

在我看来,这可能是在检查实际上r[2*i],r[2*i+1]等的读取值没有超出数组本身的限制。

您能提出一种不会引起这些检查的解决方案,并可能解释为什么它会更好吗?

athrunyang 回答:Cython:从类型化的memoryview数组中读取值的最快方法是什么?

您可能想看一下添加here中列出的一些编译器指令,例如boundscheck和wraparound。您可以使用这些特殊的装饰器注释cython函数,以消除您看到的这些检查。

本文链接:https://www.f2er.com/3083916.html

大家都在问