簡體   English   中英

如何在cython中為np.ndarray處理內存?

[英]How is memory handled for np.ndarray in cython?

例如,如果我這樣做:

cdef np.ndarray[np.int64_t, ndim=1] my_array

我的my_array存儲在哪里? 我認為,因為我沒有告訴cython存儲在堆上它會存儲在堆棧上,但是在進行下面的實驗之后,它似乎存儲在堆上,或者以某種方式有效地管理內存。 如何針對my_array管理內存? 也許我錯過了一些明顯的東西,但我找不到任何文件。

import numpy as np
cimport cython
cimport numpy as np

from libc.stdlib cimport malloc, free

def big_sum():
    # freezes up:
    # "a" is created on the stack
    # space on the stack is limited, so it runs out

    cdef int a[10000000]

    for i in range(10000000):
        a[i] = i

    cdef int my_sum
    my_sum = 0
    for i in range(10000000):
        my_sum += a[i]
    return my_sum

def big_sum_malloc():
    # runs fine:
    # "a" is stored on the heap, no problem

    cdef int *a
    a = <int *>malloc(10000000*cython.sizeof(int))

    for i in range(10000000):
        a[i] = i

    cdef int my_sum
    my_sum = 0
    for i in range(10000000):
        my_sum += a[i]

    with nogil:
        free(a) 
    return my_sum    

def big_numpy_array_sum():
    # runs fine:
    # I don't know what is going on here
    # but given that the following code runs fine,
    # it seems that entire array is NOT stored on the stack

    cdef np.ndarray[np.int64_t, ndim=1] my_array
    my_array = np.zeros(10000000, dtype=np.int64)

    for i in range(10000000):
        my_array[i] = i

    cdef int my_sum
    my_sum = 0
    for i in range(10000000):
        my_sum += my_array[i]
    return my_sum

Cython在這里沒有做任何神奇的事情。 Numpy有一個完整的C-api,這就是cython與之交互的東西 - cython本身沒有執行內存管理,而numpy數組中的內存處理方式與使用python中的numpy數組時的處理方式相同。 @Bakuriu是對的 - 這絕對是在堆上。

考慮一下這個cython代碼:

cimport numpy as np
def main():
    zeros = np.zeros
    cdef np.ndarray[dtype=np.double_t, ndim=1] array
    array = zeros(10000)

這將在等效的main函數中轉換為以下C. 我刪除了聲明和錯誤處理代碼,使其更清晰。

PyArrayObject *__pyx_v_array = 0;
PyObject *__pyx_v_zeros = NULL;
PyObject *__pyx_t_1 = NULL;
PyObject *__pyx_t_2 = NULL;

// zeros = np.zeros             # <<<<<<<<<<<<<<
// get the numpy module object
__pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s__np);
// get the "zeros" function
__pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s__zeros)
__pyx_v_zeros = __pyx_t_2;

// array = zeros(10000)             # <<<<<<<<<<<<<<
// (__pyx_k_tuple_1 is a static global variable containing the literal python tuple
// (10000, ) that was initialized during the __Pyx_InitCachedConstants function)
__pyx_t_2 = PyObject_Call(__pyx_v_zeros, ((PyObject *)__pyx_k_tuple_1), NULL);
__pyx_v_array = ((PyArrayObject *)__pyx_t_2);

如果你查看numpy C api文檔,你會發現PyArrayObject是numpy ndarray的C-api結構。 這里的關鍵點是看到cython根本沒有明確地處理內存分配。 相同的面向對象的設計原則適用於python和numpy C apis,這里的內存管理是PyArrayObject的責任。 這種情況與在python中使用numpy數組沒有什么不同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM