2013-11-15 5 views
12

उदाहरण के लिए यदि मैं यह कर? मुझे लगता है कि चूंकि मैंने ढेर पर स्टोर करने के लिए साइथन को नहीं बताया था, इसलिए इसे स्टैक पर संग्रहीत किया जाएगा, लेकिन निम्नलिखित प्रयोग करने के बाद ऐसा लगता है कि यह ढेर पर संग्रहीत है, या किसी भी तरह कुशलतापूर्वक स्मृति प्रबंधित है। स्मृति को my_array के संबंध में कैसे प्रबंधित किया जाता है? शायद मुझे कुछ याद आ रही है, लेकिन मुझे इस पर कोई दस्तावेज नहीं मिला।साइथन में 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

आप जेनरेट की गई सी फ़ाइल को क्यों न देखें? वैसे भी मुझे विश्वास है कि साइथन बस आवंटन के लिए numpy कार्यों को बुलाता है, जो 'PyMalloc' कहते हैं जो ढेर पर आवंटित करता है। numpy * नहीं * इसकी याददाश्त का प्रबंधन करता है। यह बस पाइथन आवंटन/deallocations पर निर्भर करता है। – Bakuriu

+1

@ बाकुरीयू, आपकी टिप्पणी के लिए धन्यवाद, यह समझ में आता है और बहुत मदद करता है, लेकिन क्या आप ऐसे स्रोत के बारे में जानते हैं जो उन चरणों को अधिक विस्तार से बताता है? मैंने जेनरेट की गई सी फ़ाइल को देखने की कोशिश की, लेकिन यह कोड की 6000 से अधिक लाइनें है, और मैं इसे अधिक समझ नहीं पाया। – Akavall

+0

यह लगभग निश्चित रूप से ढेर है - मान लें कि सरणी का आकार घोषणापत्र समय पर ज्ञात नहीं है, आमतौर पर बड़े एरे और स्टैक पर काम करता है। यद्यपि स्टैक अनुकूलन तकनीकी रूप से संभव है, 'ndarray का विचार देखा जा सकता है, इस प्रकार डेटा संदर्भ मौजूदा दायरे से बच सकता है। इस प्रकार, ढेर में इसे लागू करने के लिए यह आसान तरीका है। यदि संभव हो तो मेमोरी व्यू का उपयोग करें, या 'मेमोरी व्यू के http://docs.cython.org/src/userguide/memoryviews.html के लिए http://docs.cython.org/src/tutorial/numpy.html –

उत्तर

1

साइथन यहां जादुई कुछ भी नहीं कर रहा है। नम्पी के पास एक पूर्ण सी-एपीआई है, और यही वह है जो साइथन बातचीत कर रहा है - साइथन मेमोरी मैनेजमेंट खुद ही नहीं कर रहा है, और नुकीले सरणी में मेमोरी उसी तरह से संभाली जाती है जब यह अजगर से एक numpy सरणी का उपयोग करते हैं। @ बाकुरीयू सही है - यह निश्चित रूप से ढेर पर है।

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

यह बराबर मुख्य कार्य में निम्नलिखित सी में अनुवाद किया जाता है:

इस cython कोड पर विचार करें। मैंने इसे साफ़ करने के लिए क्लीनर बनाने के लिए घोषणाओं और त्रुटि हैंडलिंग कोड को हटा दिया है।

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 सी API दस्तावेज़ों को देखने, आप पाएंगे कि PyArrayObject numpy ndarray के सी-api struct है देखेंगे। यहां मुख्य बिंदु यह देखना है कि साइथन स्पष्ट रूप से मेमोरी आवंटन को संभाल नहीं रहा है। वही वस्तु उन्मुख डिजाइन सिद्धांत पायथन और numpy सी apis के साथ लागू होते हैं, और यहां स्मृति प्रबंधन PyArrayObject की ज़िम्मेदारी है। पाइथन में एक numpy सरणी के उपयोग से स्थिति अलग नहीं है।

संबंधित मुद्दे