看不到Cython的提速

问题描述

我正在尝试使用Cython来加速某些数字代码中某些昂贵的Python循环的速度,但是遇到了一个问题,即我几乎看不到任何加速,并且认为我可能必须对更多的我进行cythonize处理。代码超出了我的期望。

作为一个例子,假设我有以下两个已被cythonized的函数,它们是较大类的一部分:

tm::inspect()

如上所示,def update(self,double[::1] state_data,double[::1] sensor_data,double sigma): cdef int i cdef int N = state_data.shape[0] for i in range(N): self.output[i] = self.process_sensor_data(state_data[i],sensor_data,sigma) def process_sensor_data(self,double current_state,double sigma): cdef int i cdef int N = sensor_data.shape[0] cdef double x cdef double y for i in range(N): x += self.do_something(current_state,sigma) y += self.do_something_else(sensor_data) return min(x,y) 函数接受一些numpy数组(update())和浮点数,然后运行一个调用double[::1]函数的for循环。然后,process_sensor_data()函数运行自己的for循环,该循环调用另外两个称为process_sensor_data()do_something()函数,它们已在类的其他位置定义。

现在让我们假设我可以完全do_something_else()函数进行cythonize,从而可以将其定义为具有功能标头的快速do_something()函数,例如

cdef

但我无法对cdef double do_something(self,double sigma): ... 函数进行cythonize(例如,它可能会调用numpy或scipy库中的某些函数)。这是否意味着do_something_else()process_sensor_data()内部的for循环仍将以与普通Python for循环类似的速度运行,并且看不到Cython带来的很大提速?

以另一种方式,如果我像上面那样对一个for循环进行cythonize处理,但是for循环中有一些函数调用和/或计算无法被cythonize处理(即,如果Cython的html注释输出显示了一些黄色代码行在for循环中),这是否意味着我在使用Cython时不会看到太多的提速?

不幸的是,根据我自己的实验,似乎是这种情况,但是我想确保自己不会发疯。在我的代码中,我有一个函数在Python中执行大约需要20秒,但是在我尝试对慢速循环进行cythonize之后仍然需要大约20秒才能执行。我花了好几个小时努力尝试对所有在for循环中调用的变量和函数进行cython编程,我开始认为实现该类将更简单,更易读在C ++中。谢谢您的任何帮助或指导。

解决方法

Cython并不总是更快,特别是如果您继续使用Python数据类型而不是C数据类型时。另外,请注意,Python和C数据类型之间的转换可能会在Cython中隐式发生,并且可能会很昂贵。

您还可以看看numba的nopython装饰器和pypy3。