2015-03-25 2 views
6

Я пытаюсь написать код питона, который вызывает следующие функции Cython test1 как это:Ошибка памяти, вызывающая функцию cython с большими параметрами массива 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 

мой чистый код Python будет вызывать test1 и проходит 3 Numpy массивов в качестве параметров, и они очень большие (около 10^4 * 10^3). Тест1 в свою очередь вызовет test2, который определяется ключевыми словами cdef и передает эти массивы. Поскольку test1 нужно вызывать test2 много раз (около 10^5), прежде чем он вернется, а test2 не нужно вызывать вне кода cython, я использую cdef вместо def.

Но проблема в том, что каждый раз, когда test1 вызывает test2, память начинает неуклонно возрастать. Я пытался позвонить gc.collect() за пределами этого кода на языке cython, но он не работает. И, наконец, программа будет убита системой, потому что она съела все воспоминания. Я заметил, что эта проблема возникает только с cdef и cpdef функция, и если я изменю ее на def, она отлично работает.

Я думаю, что тест1 должен передавать ссылки этих массивов на test2 вместо объекта. Но кажется, что он создает новые объекты этих массивов и передает их test2, и эти объекты никогда не затрагиваются python gc впоследствии.

Я пропустил что-то?

+0

Я не могу воспроизвести проблему. Передача 'np.ones ((10 ^^ 4, 10 ^^ 3), dtype = ...)' для 'ndk, nkw, phi' и запускать' test1' несколько раз отлично работает. Похоже, что память сильно не увеличивается. – colinfang

ответ

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

Смежные вопросы