Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 看到Cython没有加速_Python_Python 3.x_Cython_Cythonize - Fatal编程技术网

Python 看到Cython没有加速

Python 看到Cython没有加速,python,python-3.x,cython,cythonize,Python,Python 3.x,Cython,Cythonize,我试图用Cython来加速一些数值代码中昂贵的Python for循环,但遇到了一个问题,我几乎看不到任何加速,我想我可能不得不对我的代码进行Cython化,这比我希望的要多得多 举个例子,假设我有以下两个函数,它们已经被cythonized,并且是一个更大类的一部分: def update(self, double[::1] state_data, double[::1] sensor_data, double sigma): cdef int i cdef int N = s

我试图用Cython来加速一些数值代码中昂贵的Python for循环,但遇到了一个问题,我几乎看不到任何加速,我想我可能不得不对我的代码进行Cython化,这比我希望的要多得多

举个例子,假设我有以下两个函数,它们已经被cythonized,并且是一个更大类的一部分:

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[::1] sensor_data, 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)
如上所述,
update()
函数接受一些numpy数组(
double[::1]
)和一个浮点数,然后运行一个for循环,调用
process\u sensor\u data()
函数。然后,
process\u sensor\u data()
函数运行自己的for循环,该循环调用另外两个函数,分别称为
do\u something()
do\u something\u else()
,它们是在类中的其他地方定义的

现在让我们假设我可以将
dou_something()
函数完全循环化,从而可以将其定义为一个带有函数头的fast
cdef
函数

cdef double do_something(self, double current_state, double sigma):
    ...

但是我无法对
do\u something\u else()
函数进行循环化(例如,它可能会调用numpy或scipy库中的某些函数)。这是否意味着
过程中的for循环_sensor_data()
更新()
仍将以与vanilla Python for循环类似的速度运行,而Cython不会有太大的加速

换句话说,如果我像上面那样对for循环进行cythonize,但是for循环中有一些函数调用和/或计算无法进行cythonized(即,如果Cython的html注释输出在for循环中显示一些黄色代码行),这是否意味着我在使用Cython时不会看到太多的加速


从我自己的实验来看,不幸的是似乎是这样,但我想确保我没有发疯。在我的代码中,有一个函数在Python中执行大约需要20秒,但在我尝试将慢速for循环循环循环化之后,仍然需要大约20秒来执行。我花了好几个小时,在兔子洞里尝试尽可能多地在调用循环中调用变量和函数,我开始认为在C++中实现类更简单,更易读。任何帮助或指导都将不胜感激,谢谢。

Cython并不总是更快,特别是如果您继续使用Python数据类型而不是C数据类型。另外,请注意,Python和C数据类型之间的转换可以在Cython中隐式进行,而且代价可能很高


你也可以看看numba的Nopyton decorator和pypy3。

“这是否意味着进程中的for循环\u sensor\u data()和update()仍将以与vanilla Python for循环类似的速度运行,而Cython没有太多的加速?”-这取决于你的意思,但它们是外部循环,因此,对它们进行循环化比CythoNosion内环要重要得多。在C++中实现这一点不太可能产生更好的加速,除非你可以用C++来处理不能进行循环编程的NUMPY/SISPY函数。即使如此,如果NumPy/SciPy功能已经用C编写,可能也没有多大帮助。通常在这种情况下,跨绑定是昂贵的,如果您需要调用NumPy,并且为此必须将本机数据转换为python对象,您将面临一些开销,如果你可以调用C版本的numpy,那么它会更快,但我不知道这是否可能。看看这里,似乎可以从cython调用numpy,而不需要过多的对象转换hanks@geckos,该页面提供了使用类型化MemoryView处理numpy数组并仍然能够快速编写cython代码的好例子,但不幸的是,它似乎没有提到使用numpy函数并仍然能够快速编写cython代码(在循环示例中,他们必须重新编写
np.clip()
),这对于非类函数来说是非常好的,但是尝试
jit
Python类是一个非常头疼的问题,并且会降低代码的可读性。我也尝试过pypy3,但它似乎不适用于我经常使用的一些python库(例如,
rospy
)。在尝试使用numba和Py3并失败之后,cython感觉自己是试图用Python编写快速数值/科学计算代码的“最后希望”。然而,在看到cythonized循环速度没有得到提高(如果它们中有numpy和scipy函数调用)之后,快速Python代码似乎是不可能的:(您是否尝试了探查器?可能热点在某个不明显的地方?是的,95%的处理时间发生在已识别的单个函数中。