2013-11-15 24 views
12

bunu yaparsam? Cython'un yığında saklanacağını söylemediğimden beri, yığın üzerinde saklanacağını düşünürdüm, ancak aşağıdaki denemeyi yaptıktan sonra, yığında saklandığını ya da bir şekilde verimli bir şekilde belleğin yönetildiğini görüyoruz. Bellek my_array'a göre nasıl yönetiliyor? Belki bariz bir şey eksik, ama üzerinde herhangi bir belge bulamadım.Bellek np.ndarray için cython'da nasıl kullanılır?</p> <pre><code>cdef np.ndarray[np.int64_t, ndim=1] my_array </code></pre> <p>Nerede benim <code>my_array</code> depolanır: Örneğin

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

Neden oluşturulan C dosyasına bir göz atmıyorsunuz? Her neyse, cython'un, tahsis için “pyMalloc” diye adlandırılan ve çağrı için tahsis edilen numpy işlevlerini çağırdığına inanıyorum. numpy yok * belleğini yönetmiyor. Sadece python tahsislerine/tahsisatlara dayanır. – Bakuriu

+1

@Bakuriu, Yorumunuz için teşekkürler, bu mantıklı ve çok yardımcı olur, ancak bu adımları daha ayrıntılı olarak açıklayan bir kaynak biliyor musunuz? Oluşturulan C dosyasına bakmayı denedim, ancak 6000'den fazla kod içeriyor ve ben bunu anlayamadım. – Akavall

+0

Neredeyse kesinlikle yığın oluyor - dizinin boyutunun bildirme zamanında bilinmediğini düşünün, genellikle büyük dizilerde çalışır ve yığın sınırlı. Yığın optimizasyonu teknik olarak mümkün olsa da, ndarray'ın görünümleri olabilir, bu nedenle veri referansı geçerli kapsamdan çıkabilir. Bu şekilde, onu yığın halinde uygulamak daha kolaydır. Mümkünse bir MemoryView kullanın veya http://docs.cython.org/src/userguide/memoryviews.html için http://docs.cython.org/src/tutorial/numpy.html –

cevap

1

Cython burada büyülü bir şey yapmıyor. Numpy tam bir C-api'ye sahiptir ve bu, cython'un etkileşim kurduğu şeydir - cython bellek yönetiminin kendisini gerçekleştirmez ve numpy dizisindeki bellek, python'dan bir numpy dizisi kullanırken olduğu gibi ele alınır. @Bakuriu haklı - bu kesinlikle yığında.

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

Bu eşdeğer ana işlevi aşağıdaki C için tercüme:

bu Cython kodu düşünün. Okumayı daha temiz hale getirmek için beyanları ve hata işleme kodunu kaldırdım.

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

Eğer numpy C API belgelerine yukarı bakarsanız, PyArrayObject numpy ndarray C-api yapı olduğunu göreceksiniz. Buradaki kilit nokta, cython'un açıkça bellek ayırma işlemlerini ele almadığını görmektir. Aynı nesne yönelimli tasarım ilkeleri python ve numpy C apis ile uygulanır ve burada bellek yönetimi PyArrayObject'in sorumluluğundadır. Durum python'da numpy dizisinin kullanımından farklı değildir.

İlgili konular