2012-07-02 12 views
30

मेरी धारणा यह है कि न्यूमपी में, दो सरणी एक ही स्मृति साझा कर सकते हैं। निम्न उदाहरण लें:क्या यह जांचने का कोई तरीका है कि NumPy arrays समान डेटा साझा करते हैं या नहीं?

import numpy as np 
a=np.arange(27) 
b=a.reshape((3,3,3)) 
a[0]=5000 
print (b[0,0,0]) #5000 

#Some tests: 
a.data is b.data #False 
a.data == b.data #True 

c=np.arange(27) 
c[0]=5000 
a.data == c.data #True (Same data, not same memory storage), False positive 

तो स्पष्ट रूप से ba की एक प्रतिलिपि बनाने नहीं किया था; इसने अभी कुछ नया मेटा-डेटा बनाया है और इसे उसी मेमोरी बफर से जोड़ा है जो a उपयोग कर रहा है। क्या यह जांचने का कोई तरीका है कि दो सरणी एक ही मेमोरी बफर का संदर्भ देते हैं या नहीं?

मेरा पहला प्रभाव a.data is b.data का उपयोग करना था, लेकिन यह झूठा रिटर्न देता है। मैं a.data == b.data कर सकता हूं जो सच देता है, लेकिन मुझे नहीं लगता कि a और b एक ही मेमोरी बफर साझा करें, केवल a द्वारा संदर्भित स्मृति की ब्लॉक और b द्वारा संदर्भित एक ही बाइट्स है।

+2

यहां सबसे प्रासंगिक प्रश्न पूछा गया है: http://stackoverflow.com/questions/10747748/how-do-i-check-that-two-slices-of-numpy-arrays-are-the-same- या ओवरलैपिंग –

+1

@RobertKern - धन्यवाद। मैंने वास्तव में उस पोस्ट को देखा था, लेकिन चूंकि मुझे 'numpy.may_share_memory' के लिए प्रलेखन नहीं मिला (अंतर्निहित 'सहायता' के अलावा), मैंने सोचा कि कुछ और हो सकता है - उदा। 'Numpy.uses_same_memory_exactly'। (मेरा उपयोग मामला दूसरे की तुलना में थोड़ा कम सामान्य है, इसलिए मैंने सोचा कि एक और निश्चित उत्तर हो सकता है)। वैसे भी, कुछ नामांकित मेलिंग सूचियों पर आपका नाम देखा है, मैं अनुमान लगा रहा हूं कि जवाब "ऐसा कोई कार्य नहीं है"। – mgilson

+1

'numpy.may_share_memory()' संदर्भ मैनुअल के संगठन के दुर्घटना के कारण संदर्भ मैनुअल में दिखाई नहीं देता है। उपयोग करने के लिए यह सही बात है। दुर्भाग्यवश, इस समय कोई 'util_same_memory_exactly()' फ़ंक्शन नहीं है। इस तरह के एक समारोह को लागू करने के लिए एक बाध्य रैखिक डायफोंटाइन समीकरण, एनपी-हार्ड समस्या को हल करने की आवश्यकता होती है। समस्या का आकार आमतौर पर बहुत बड़ा नहीं होता है, लेकिन केवल एल्गोरिदम लिखना परेशान होता है, इसलिए यह अभी तक नहीं किया गया है। यदि हम करते हैं, तो इसे 'numpy' में शामिल किया जाएगा।may_share_memory() ', इसलिए मैं इसका उपयोग करने की अनुशंसा करता हूं। –

उत्तर

8

मुझे लगता है कि jterrace का जवाब शायद जाने के लिए सबसे अच्छा तरीका है, लेकिन यहाँ एक और संभावना है।

def byte_offset(a): 
    """Returns a 1-d array of the byte offset of every element in `a`. 
    Note that these will not in general be in order.""" 
    stride_offset = np.ix_(*map(range,a.shape)) 
    element_offset = sum(i*s for i, s in zip(stride_offset,a.strides)) 
    element_offset = np.asarray(element_offset).ravel() 
    return np.concatenate([element_offset + x for x in range(a.itemsize)]) 

def share_memory(a, b): 
    """Returns the number of shared bytes between arrays `a` and `b`.""" 
    a_low, a_high = np.byte_bounds(a) 
    b_low, b_high = np.byte_bounds(b) 

    beg, end = max(a_low,b_low), min(a_high,b_high) 

    if end - beg > 0: 
     # memory overlaps 
     amem = a_low + byte_offset(a) 
     bmem = b_low + byte_offset(b) 

     return np.intersect1d(amem,bmem).size 
    else: 
     return 0 

उदाहरण:

>>> a = np.arange(10) 
>>> b = a.reshape((5,2)) 
>>> c = a[::2] 
>>> d = a[1::2] 
>>> e = a[0:1] 
>>> f = a[0:1] 
>>> f = f.reshape(()) 
>>> share_memory(a,b) 
80 
>>> share_memory(a,c) 
40 
>>> share_memory(a,d) 
40 
>>> share_memory(c,d) 
0 
>>> share_memory(a,e) 
8 
>>> share_memory(a,f) 
8 

यहाँ प्रत्येक share_memory(a,a[::2]) अपने कंप्यूटर पर a में तत्वों की संख्या के एक समारोह के रूप में कॉल के लिए समय दिखा एक साजिश है।

share_memory function

+4

पर निर्भर होना चाहिए। ऐसे में कोई विचार हो सकता है जो विभिन्न आइटम्स के साथ भी स्मृति साझा करता हो। उदाहरण के लिए, मुझे एक 'फ्लोट 32' के रूप में एक सरणी को वास्तविक और काल्पनिक घटकों के साथ मिल सकता है और इसे 'complex64' सरणी के रूप में देख सकता है। एक अधिक विश्वसनीय कार्यान्वयन 'numpy.may_share_memory()' में है। –

+0

@RobertKern: अच्छा बिंदु। मैंने अपना जवाब अपडेट कर लिया है। क्या आप इस समाधान के साथ कोई संभावित समस्या देखते हैं? – user545424

+0

मुझे लगता है कि मुझे अंत में यह सही मिला है। 'share_memory()' प्रत्येक सरणी के आकार के योग के क्रम में स्मृति की आवश्यकता है, लेकिन यह बहुत तेज़ है। – user545424

26

आप एक सरणी एक और सरणी के साथ स्मृति के शेयरों अगर जाँच करने के लिए base विशेषता का उपयोग कर सकते हैं: कि

>>> import numpy as np 
>>> a = np.arange(27) 
>>> b = a.reshape((3,3,3)) 
>>> b.base is a 
True 
>>> a.base is b 
False 

सुनिश्चित नहीं हैं कि अगर आपकी समस्या नहीं सुलझती। यदि सरणी की अपनी याददाश्त है तो मूल विशेषता None होगी। ध्यान दें कि एक सरणी के आधार एक और सरणी हो जाएगा, भले ही वह एक सबसेट है:

>>> c = a[2:] 
>>> c.base is a 
True 
+0

यह शायद मेरे उद्देश्यों के लिए पर्याप्त है। यह दुर्भाग्यपूर्ण है कि यह 2-तरफा सड़क नहीं है। मैं इंतजार करूंगा और देख सकता हूं कि कुछ और बेहतर हो जाता है या नहीं। इस बीच, धन्यवाद। (+1) – mgilson

+0

आप कर सकते हैं 'ए.बेस बी है या बी .बेस एक है। – user545424

+4

यह अविश्वसनीय है। प्रत्येक सरणी में '.base' विशेषताओं की श्रृंखला हो सकती है, उदा। 'a.base.base बी है सत्य हो सकता है। उसी 'स्मृति' को साझा किए बिना उसी स्मृति को इंगित करने के लिए Arrays का निर्माण भी किया जा सकता है। –

4

बस कार्य करें:

a = np.arange(27) 
a.__array_interface__['data'] 

दूसरी पंक्ति एक टपल वापस आ जाएगी जहां पहली प्रविष्टि स्मृति पता है और दूसरा कि क्या सरणी केवल पढ़ने के लिए है। आकार और डेटा प्रकार के साथ, आप सरणी को कवर करने वाले मेमोरी पते की सटीक अवधि का पता लगा सकते हैं, ताकि जब आप एक सरणी दूसरे का सबसेट हो, तो आप इससे भी काम कर सकते हैं।

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

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