内存泄漏调用cython函数与大numpy数组参数?

Yan*_*uan 6 python numpy cython

我正在尝试编写调用以下cython函数test1的python代码,如下所示:

def test1( np.ndarray[np.int32_t, ndim=2] ndk, 
           np.ndarray[np.int32_t, ndim=2] nkw, 
           np.ndarray[np.float64_t, ndim=2] phi):

    for _ in xrange(int(1e5)):
        test2(ndk, nkw, phi)


cdef int test2(np.ndarray[np.int32_t, ndim=2] ndk,
               np.ndarray[np.int32_t, ndim=2] nkw,
               np.ndarray[np.float64_t, ndim=2] phi):
    return 1
Run Code Online (Sandbox Code Playgroud)

我的纯python代码将调用test1并传递3个numpy数组作为参数,它们非常大(大约10 ^ 4*10 ^ 3).test1将依次调用使用cdef关键字定义的test2 并传递这些数组.由于test1需要在返回之前多次调用test2(大约10 ^ 5),并且不需要在cython代码之外调用test2,我使用cdef而不是def.

但问题是,每次test1调用test2时,内存开始稳定增加.我试图gc.collect()在这个cython代码之外调用,但它不起作用.最后,程序将被系统杀死,因为它消耗了所有的记忆.我注意到这个问题只发生在cdefcpdef函数中,如果我将其更改为def,它可以正常工作.

我认为test1应该将这些数组的引用传递给test2而不是对象.但似乎它创建了这些数组的新对象并将它们传递给test2,之后这些对象永远不会被python gc触及.

我错过了什么?

Yan*_*uan 2

我对这个问题仍然很困惑。但我找到了另一种方法来绕过这个问题。只需明确告诉 cython 传递指针,如下所示:

def test1( np.ndarray[np.int32_t, ndim=2] ndk, 
           np.ndarray[np.int32_t, ndim=2] nkw, 
           np.ndarray[np.float64_t, ndim=2] phi):

for _ in xrange(int(1e5)):
    test2(&ndk[0,0], &nkw[0,0], &phi[0,0])


cdef int test2(np.int32_t* ndk,
               np.int32_t* nkw,
               np.float64_t* phi):
    return 1
Run Code Online (Sandbox Code Playgroud)

但是,您需要像这样索引数组:ndk[i*row_len + j] 详细信息:https://github.com/cython/cython/wiki/tutorials-NumpyPointerToC