2015-03-25 24 views
6

我想編寫調用下面用Cython功能測試1這樣的Python代碼:內存泄漏調用具有大型numpy數組參數的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, 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 

我的純Python代碼調用test1的,並通過3個numpy的數組作爲參數,它們是非常大的(約10^4×10^3)。 test1將依次調用test2,該測試使用cdef關鍵字定義,並傳遞這些數組。由於test1在返回之前需要多次調用test2(大約10^5),並且test2不需要在cython代碼之外調用,所以我使用cdef而不是def

但問題是,每當test1調用test2時,內存開始穩步增加。我試圖在這個Cython代碼之外調用gc.collect(),但它不起作用。最後,該程序將被系統殺死,因爲它已經吃掉了所有的記憶。我注意到這個問題只發生在cdefcpdef函數,如果我改變它爲def它工作正常。

我認爲test1應該將這些數組的引用傳遞給test2而不是對象。但它似乎創建了這些數組的新對象並將它們傳遞給test2,之後這些對象從未被python gc觸及。

我錯過了什麼嗎?

+0

我無法重現該問題。將'np.ones((10 ^^ 4,10 ^^ 3),dtype = ...)'傳遞給'ndk,nkw,phi'並且多次運行'test1'可以正常工作。內存似乎並沒有增加太多。 – colinfang 2015-03-27 01:16:27

回答

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 

但是,您將需要指數數組是這樣的:ndk[i*row_len + j] 詳細信息:https://github.com/cython/cython/wiki/tutorials-NumpyPointerToC