简体   繁体   English

如何在cython中为np.ndarray处理内存?

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

For example if I do this: 例如,如果我这样做:

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

Where is my my_array stored? 我的my_array存储在哪里? I would think that since I didn't tell cython to store in on the heap it would be stored on the stack, but after doing the following experiment it seems that it is stored on the heap, or somehow efficiently memory managed. 我认为,因为我没有告诉cython存储在堆上它会存储在堆栈上,但是在进行下面的实验之后,它似乎存储在堆上,或者以某种方式有效地管理内存。 How is memory managed with respect to my_array ? 如何针对my_array管理内存? Maybe I am missing something obvious, but I couldn't find any documentation on it. 也许我错过了一些明显的东西,但我找不到任何文件。

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 is not doing anything magical here. Cython在这里没有做任何神奇的事情。 Numpy has a full C-api, and that's what cython is interacting with -- cython is not performing the memory management itself, and memory in the numpy array is handled the same way it is when using a numpy array from python. Numpy有一个完整的C-api,这就是cython与之交互的东西 - cython本身没有执行内存管理,而numpy数组中的内存处理方式与使用python中的numpy数组时的处理方式相同。 @Bakuriu is right -- this is definitely on the heap. @Bakuriu是对的 - 这绝对是在堆上。

Consider this cython code: 考虑一下这个cython代码:

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

This gets translated to the following C in equivalent main function. 这将在等效的main函数中转换为以下C. I've removed the declarations and error handling code to make it cleaner to read. 我删除了声明和错误处理代码,使其更清晰。

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);

If you look up the numpy C api documentation, you'll see that PyArrayObject is the numpy ndarray's C-api struct. 如果你查看numpy C api文档,你会发现PyArrayObject是numpy ndarray的C-api结构。 The key point here is to see that cython isn't explicitly handling memory allocation at all. 这里的关键点是看到cython根本没有明确地处理内存分配。 The same object orientated design principles apply with the python and numpy C apis, and memory management here is the responsibility of PyArrayObject. 相同的面向对象的设计原则适用于python和numpy C apis,这里的内存管理是PyArrayObject的责任。 The situation no different from the use of a numpy array in python. 这种情况与在python中使用numpy数组没有什么不同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM