2015-03-25 9 views
6

Sto cercando di scrivere il codice python che chiama le seguenti funzioni test1 Cython come questo:perdita di memoria chiamata funzione cython con grandi parametri di array numpy?

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 

il mio codice Python puro chiamerà test1 e passare 3 array NumPy come parametri, e sono molto grandi (circa 10^4 * 10^3). Il test1 chiamerà a sua volta il test2 che è definito con le parole chiave cdef e passa tali matrici. Poiché il test1 deve chiamare test2 molte volte (circa 10^5) prima che ritorni, e test2 non deve essere chiamato al di fuori del codice cython, io uso cdef invece di def.

Ma il problema è che ogni volta che test1 chiama test2, la memoria inizia ad aumentare costantemente. Ho provato a chiamare gc.collect() al di fuori di questo codice cython, ma non funziona. E infine, il programma verrà ucciso dal sistema, poiché ha consumato tutti i ricordi. Ho notato che questo problema si verifica solo con la funzione cdef e cpdef e se la cambio in def funziona correttamente.

Penso che test1 debba passare i riferimenti di questi array a test2 anziché oggetto. Ma sembra come se creasse nuovi oggetti di questi array e li passasse a test2, e questi oggetti non vengono mai toccati dal python gc in seguito.

mi sono perso qualcosa?

+0

non riesco a riprodurre il problema. Passare 'np.ones ((10 ^^ 4, 10 ^^ 3), dtype = ...)' per 'ndk, nkw, phi' ed eseguire' test1' più volte funziona bene. La memoria non sembra aumentare molto. – colinfang

risposta

2

Sono ancora confuso su questo problema. Ma ho trovato un altro modo per aggirare questo problema. Basta dire esplicitamente il Cython per passare il puntatore in questo modo:

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 

Tuttavia, è necessario per indicizzare l'array come questo: ndk[i*row_len + j] Dettagli: https://github.com/cython/cython/wiki/tutorials-NumpyPointerToC