2011-11-30 10 views
15

मैं Ukkonen के एल्गोरिदम पर आधारित गणित में एक प्रत्यय पेड़ बनाने के लिए एक एल्गोरिदम कोडिंग कर रहा हूँ।क्या डेटा को बड़ी मात्रा में डेटा के साथ पास करने से गणित में बहुत सारी मेमोरी और समय खर्च होता है?

मेरे पास जो प्रश्न है, वह मेरे पूरे वृक्ष संरचना (जिसे मैंने सूची में संग्रहीत किया है) को पार करने के लिए एक समारोह में गुजरना होगा, मेरे कार्यक्रम को बहुत मेमोरी और समय खर्च करना होगा क्योंकि मुझे कुछ कार्यों का उपयोग करना है एल्गोरिदम में कई बार?

उदाहरण के लिए, मेरे पास एक ऐसा फ़ंक्शन है जो एक विशिष्ट नोड के बच्चों की खोज करता है, और मैं पूरे पेड़ को खोजने के लिए Select फ़ंक्शन का उपयोग करता हूं।

getChildren[parentID_] := Select[tree, #[[3]] == parentID &]; 

हालांकि मुझे पेड़ तक पहुंचने की ज़रूरत है, तो क्या पूरे वृक्ष संरचना को कार्य में पार करना उचित है? चूंकि ऐसा प्रतीत नहीं होता है कि संपूर्ण नोटबुक में परिवर्तनीय वैश्विक बनाने का एक तरीका है। या इस के आसपास पाने के लिए कुछ वैकल्पिक तरीका है?

+4

आप मतलब है "वहाँ एक बनाने के लिए कोई रास्ता नहीं है परिवर्तनीय वैश्विक पूरी नोटबुक में "? यदि आप 'वृक्ष = 5' को परिभाषित करते हैं तो' ग्लोबल 'संदर्भ में' पेड़ '5 हर जगह है (जो डिफ़ॉल्ट है)। यह डिफ़ॉल्ट रूप से वैश्विक है, जब तक आप किसी अन्य व्यवहार के बाद नहीं होते। – acl

उत्तर

23

नहीं, अभिव्यक्तियों को पारित करने के लिए अतिरिक्त स्मृति खर्च नहीं होती है। जैसा कि कार्यात्मक भाषाओं में सामान्य है, गणित वस्तुएं immutable हैं: उन्हें संशोधित नहीं किया जा सकता है, इसके बजाय जब आप कुछ फ़ंक्शन का उपयोग करके उन्हें बदलते हैं तो एक नई वस्तु बनाई जाती है। इसका यह भी अर्थ है कि यदि आप उन्हें परिवर्तित नहीं करते हैं, तो उनकी प्रतिलिपि नहीं बनाई जाती है, भले ही आप उन्हें कार्यों के बीच कितना पास करते हैं।


एक उपयोगकर्ता के दृष्टिकोण से

, मेथेमेटिका भाव पेड़ हैं, लेकिन मुझे विश्वास है कि आंतरिक रूप से वे भले ही कितनी ही बार में प्रकट होता है की, directed acyclic graphs के रूप में जमा कर रहे हैं यानी एक ही उपसूचक स्मृति में केवल एक बार संग्रहित किया जा सकता है, पूर्ण अभिव्यक्ति (उदाहरण के लिए Share[] का दस्तावेज़ पृष्ठ देखें)।

In[1]:= $HistoryLength = 0; 

चेक स्मृति उपयोग:

In[2]:= MemoryInUse[] 
Out[2]= 13421756 

के एक करते हैं

पहले, सुनिश्चित करें In/Out अतिरिक्त स्मृति नहीं लेते हैं:

यहाँ वर्णन करने के लिए एक उदाहरण है अभिव्यक्ति जो स्मृति की एक उल्लेखनीय मात्रा लेती है:

In[3]:= s = [email protected][1000000]; 

In[4]:= MemoryInUse[] 
Out[4]= 17430260 

अब इस अभिव्यक्ति को दोहराने एक सौ गुना ...

In[5]:= t = ConstantArray[s, 100]; 

... और देखा कि स्मृति के उपयोग मुश्किल से बढ़ता है:

In[6]:= MemoryInUse[] 
Out[6]= 18264676 

ByeCount[] भ्रामक है क्योंकि यह वास्तविक रिपोर्ट नहीं करता भौतिक स्मृति का उपयोग किया जाता है, लेकिन स्मृति का उपयोग किया जाएगा यदि सामान्य उप-संपीड़न को समान स्मृति साझा करने की अनुमति नहीं थी:

In[7]:= ByteCount[t] 
Out[7]= 400018040 

एक दिलचस्प बात नोट करने के लिए: यदि आप s से f[...] हटाने, और दोनों s और t एक सादे संख्यात्मक सरणी, तो यह स्मृति साझा करने ऐसा नहीं होगा, और स्मृति के उपयोग ~ 400 एमबी पर चला जाएगा।


चाहे आप tree एक वैश्विक चर या getChildren का एक तर्क बनाने के लिए, यह स्मृति के उपयोग में एक फर्क नहीं होंगे।

+4

उत्कृष्ट जवाब! आपके द्वारा वर्णित तस्वीर की पुष्टि करने के लिए, एक 't' में कुछ तत्वों के लिए असाइनमेंट कर सकता है, उदाहरण के लिए:' t [[1, 1, 1]] = 2; ', और एक एकल के उदाहरण के आकार के अनुरूप स्मृति खपत में तत्काल कूद देखें। संख्यात्मक सरणी के साथ आपने जो देखा है उसका कारण सूक्ष्म है: यह केवल * है * क्योंकि 'रेंज' पैक किए गए सरणी उत्पन्न करता है, * और * आपने 'कॉन्स्टेंटअरे' (और उदा। 'तालिका') का उपयोग नहीं किया। बिंदु यह है कि, 'ConstantArray' पैक किए गए सरणी से पैक किए गए सरणी का उत्पादन करेगा, और आप स्मृति को बड़े पैक किए गए सरणी में साझा नहीं कर सकते हैं, क्योंकि यह ... –

+1

... प्रत्यक्ष सी मेमोरी लेआउट पर आधारित है। क्या आपने या तो '' ur = डेवलपर 'FromPackedArray [रेंज [1000000]] का उपयोग किया होगा; टी = ConstantArray [यूआर, {100}] '' या 'आर = रेंज [1000000]; टी = तालिका [आर, {100}]; ', और आप एक ही स्मृति साझाकरण देखा होगा, क्योंकि परिणाम पैक नहीं किया गया है (जिसका अर्थ है कि मध्यवर्ती पॉइंटर्स हैं, और साझा करना संभव है - या कम से कम यह इस समय मेरी तस्वीर है)। –

+0

मैं कुछ ऐसा करने के लिए अपरिवर्तनीयता पर बयान बदलता हूं जैसे: "उन्हें संशोधित नहीं किया जा सकता है, जब तक कि वे एक चर में संग्रहित न हों" - गणित एक शुद्ध कार्यात्मक भाषा नहीं है, और उत्परिवर्तन संभव है। –

4
स्ज़बोल्क्स को

इसके अलावा उत्तर देता है, तो आप पर पारित-दर-संदर्भ उपयोगी इस सवाल का मिल सकता है अगर आप डेटा को संशोधित करने की आवश्यकता है:

simple question on passing data between functions

+1

चूंकि आपने इस विषय को लाया है, इसलिए मुझे यह उल्लेख करने दें कि उस प्रश्न का स्वीकृत उत्तर काम करता है , मैं आमतौर पर प्रोग्राम डिज़ाइन परिप्रेक्ष्य से 'अनियंत्रित' का उपयोग करने के खिलाफ सलाह दूंगा: किसी को फ़ंक्शन स्वयं-निहित डिज़ाइन करना चाहिए, जबकि फ़ंक्शन केवल तभी काम करेगा जब उपयोगकर्ता तर्क के आस-पास 'अनियमित' को लपेटना न भूलें, और आगे, समारोह के लिए इस चूक को पकड़ने का कोई तरीका नहीं है। आईएमओ, होल्ड-एट्रिब्यूट्स को इस तरह के मामलों में 'अनियंत्रित' को दृढ़ता से प्राथमिकता दी जाती है। –

+0

@ लियोनिद - मैंने आपके उत्तर का संदर्भ देने के लिए लिंक बदल दिया। (यह वैसे भी मेरा पहला इरादा था।) –

+0

धन्यवाद, लेकिन मेरा जवाब भी एक सामान्य सिफारिश नहीं है - प्रश्न सीडीएफ के प्रतिबंधों से बाधित था जहां स्पष्ट होल्ड गुणों को प्रतीक से जोड़ा नहीं जा सकता है। जाहिर है, एसओ पर अभी तक किसी ने भी "गणित में पास-बाय-रेफरेंस" (या कम से कम मुझे इसके बारे में पता नहीं है) जैसे कुछ सरल प्रश्न पूछा है, जबकि इस तरह के विषय के लिए एसओ चर्चा होने पर बहुत वांछनीय लगता है। –