python列表上的递归,使用cython?

python列表上的递归,使用cython?,python,list,cython,Python,List,Cython,我试图使用cython来加速递归函数的速度,该函数执行numpy查找以找到感兴趣的连接区域: import numpy as np cimport numpy as np DTYPE = np.int ctypedef np.int_t DTYPE_t def find_ob(np.ndarray[DTYPE_t, ndim=2] ar, list point, list s): if ar[point[0], point[1]] == 1: s.append(poin

我试图使用cython来加速递归函数的速度,该函数执行numpy查找以找到感兴趣的连接区域:

import numpy as np
cimport numpy as np
DTYPE = np.int
ctypedef np.int_t DTYPE_t

def find_ob(np.ndarray[DTYPE_t, ndim=2] ar, list point, list s):
    if ar[point[0], point[1]] == 1:
        s.append(point)
        px = point[0]
        py = point[1]
        new_points = [[px-1, py], [px, py-1], [px+1, py], [px, py+1], 
                      [px+1, py+1], [px-1, py-1]]
        for i in new_points:
            if i not in s:
                find_ob(ar, i, s)

# From python:
ar = np.zeros((15, 15), dtype=int)
ar[2:8, 2:8] = 1

s = []
cythonmodule.find_ob(ar, point, s)
print len(s)
>>> 36

然而,我认为我正在传递一个本地python列表,因此没有得到任何加速。在传递到find_ob之前,是否需要将python列表转换为c数组、结构或其他形式?我看到了这一点:但不确定该怎么办。

您正在递归中添加一个列表:s.appendpoint,无论您是否使用C数组,这都是低效的,因为您必须分配一个大小为old array+1的新数组,复制旧数组并添加一个元素或python列表

然后在这里搜索一个列表:如果i不在s中:这意味着对于每个点i,整个列表都将被遍历以检查我是否在该列表中。在C语言中,最好使用集合或无序映射

事实上,您已经用C加速了代码中最快的操作,您的瓶颈似乎是:

for i in new_points:
        if i not in s:
            find_ob(ar, i, s)

我认为,首先可以通过更改所使用的数据结构,从python代码中获得更多信息。然后,如果您想转到c路径,请确保您从未在python列表上执行操作。

您在递归中附加到一个列表:s.appendpoint,无论您是否使用c数组,这都是低效的,因为您必须分配一个大小为old array+1的新数组,复制旧数组并添加一个元素或python列表

然后在这里搜索一个列表:如果i不在s中:这意味着对于每个点i,整个列表都将被遍历以检查我是否在该列表中。在C语言中,最好使用集合或无序映射

事实上,您已经用C加速了代码中最快的操作,您的瓶颈似乎是:

for i in new_points:
        if i not in s:
            find_ob(ar, i, s)

我认为,首先可以通过更改所使用的数据结构,从python代码中获得更多信息。然后,如果您想转到c路径,请确保您从未在python列表上执行过操作。

递归总是比迭代慢将s更改为一个集合,这将使速度明显加快:s=set,然后是s.addpoint,而不是s.append…递归总是比迭代将s更改为一个集合慢,这将使速度明显加快:s=set,然后是s.addpoint,而不是s.append…谢谢,更改为set会使速度提高8倍!谢谢,更改为sets可使速度提高8倍!