2015-03-25 17 views
6

Tôi đang cố gắng để viết mã python mà các cuộc gọi test1 chức năng cython sau như thế này:bộ nhớ bị rò rỉ gọi chức năng cython với các thông số mảng numpy lớn?

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 

mã python tinh khiết của tôi sẽ gọi test1 và vượt qua 3 mảng NumPy như thông số, và họ là rất lớn (khoảng 10^4 * 10^3). Test1 sẽ lần lượt gọi test2 được xác định với cdef từ khóa và chuyển các mảng đó. Vì test1 cần gọi test2 nhiều lần (khoảng 10^5) trước khi nó trả về, và test2 không cần phải được gọi bên ngoài mã cython, tôi sử dụng cdef thay vì def.

Nhưng vấn đề là, mỗi khi test1 gọi test2, bộ nhớ bắt đầu tăng đều đặn. Tôi đã cố gắng gọi gc.collect() bên ngoài mã cython này, nhưng nó không hoạt động. Và cuối cùng, chương trình sẽ bị hệ thống giết chết, vì nó đã ăn hết tất cả ký ức. Tôi nhận thấy rằng sự cố này chỉ xảy ra với hàm số cdefcpdef và nếu tôi thay đổi thành def hoạt động tốt.

Tôi nghĩ test1 được cho là chuyển các tham chiếu của các mảng này đến test2 thay cho đối tượng. Nhưng có vẻ như nó tạo ra các đối tượng mới của các mảng này và truyền chúng tới test2, và các đối tượng này không bao giờ bị xúc động bởi gc trăn sau đó.

tôi có bỏ lỡ điều gì đó không?

+0

Tôi không thể tạo lại vấn đề. Thông qua 'np.ones ((10 ^^ 4, 10 ^^ 3), dtype = ...)' cho 'ndk, nkw, phi' và chạy' test1' nhiều lần hoạt động tốt. Bộ nhớ dường như không tăng nhiều. – colinfang

Trả lời

2

Tôi vẫn còn bối rối về vấn đề này. Nhưng tôi tìm thấy một cách khác để vượt qua vấn đề này. Chỉ cần nói một cách rõ ràng cython để vượt qua con trỏ như thế này:

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 

Tuy nhiên, bạn sẽ cần phải chỉ số mảng như thế này: ndk[i*row_len + j] chi tiết: https://github.com/cython/cython/wiki/tutorials-NumpyPointerToC