Cython:从类型化的memoryview数组中读取值的最快方法是什么?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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]
等实际是否未超出数组本身的限制。
您能否提出一种不会引起这些检查的解决方案,并可能解释为什么它会更好地工作?
答案
您可能希望添加here中列出的一些编译器指令,例如boundscheck和wraparound。您可以使用这些特殊的修饰符来注释cython函数,以消除您看到的这些检查。
以上是关于Cython:从类型化的memoryview数组中读取值的最快方法是什么?的主要内容,如果未能解决你的问题,请参考以下文章
在 cython 中快速访问稀疏矩阵:memoryview 与字典向量
cython memoryview 不比 ndarray 快