2013-11-15 13 views
12

私はこれを行う場合は?私はヒープ上に格納するようにcythonに指示しなかったので、スタックに格納されますが、以下の実験を行った後、ヒープに格納されているか、または効率的にメモリ管理されているようです。メモリはmy_arrayに関してどのように管理されますか?たぶん私は何かを見逃しているかもしれませんが、私はそれに関する文書を見つけることができませんでした。cythonのnp.ndarrayのメモリはどのように扱われますか?</p> <pre><code>cdef np.ndarray[np.int64_t, ndim=1] my_array </code></pre> <p>はどこ<code>my_array</code>が格納されます。たとえば

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 
+4

生成されたCファイルを見てみませんか?とにかく、私はcythonが割り振りのためにnumpy関数を呼び出すと考えています。これは、ヒープに割り当てる 'PyMalloc'を呼び出します。 numpyはメモリを管理しません。単にPythonの割り当て/割り当て解除に依存しています。 – Bakuriu

+1

@Bakuriu、あなたのコメントをありがとう、それは意味があり、多くの助けになりますが、それらの手順を詳細に説明する情報源を知っていますか?私は生成されたCファイルを見てみましたが、それは6000行以上のコードであり、それをあまり理解できませんでした。 – Akavall

+0

これはほぼ確実にヒープです。宣言時に配列のサイズがわからない場合、numpyは通常大きな配列で動作し、スタックは限られています。スタックの最適化は技術的には可能ですが、 'ndarray'はビューであるため、データ参照は現在のスコープからエスケープできます。したがって、ヒープで実装する方が簡単です。可能であればMemoryViewを使用するか、http://docs.cython.org/src/tutorial/numpy.html「MemoryView'sのための –

答えて

1

ここでは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) 

これは、同等のメイン機能で、次の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配列の使用とはまったく異なります。

関連する問題