5

मैंने एक पुनरावृत्त एल्गोरिदम लागू किया है, जहां प्रत्येक पुनरावृत्ति में प्री-ऑर्डर पेड़ ट्रैवर्सल (कभी-कभी नीचे संचय कहा जाता है) के बाद एक पोस्ट ऑर्डर पेड़ ट्रैवर्सल (ऊपर संचय) होता है। प्रत्येक नोड के प्रत्येक विज़िट में अगली विज़िट के लिए उपयोग की जाने वाली जानकारी की गणना और भंडारण शामिल होता है (या तो बाद के पोस्ट-ऑर्डर ट्रैवर्सल या बाद के पुनरावृत्ति में)।समानांतर में पेड़ ट्रैवर्सिंग एल्गोरिदम लागू करने की रणनीति?

प्री-ऑर्डर ट्रेवर्सल के दौरान, प्रत्येक नोड स्वतंत्र रूप से जब तक यह और रूट के बीच सभी नोड्स पहले से ही संसाधित किया गया है संसाधित किया जा सकता। प्रसंस्करण के बाद, प्रत्येक नोड को अपने प्रत्येक बच्चे को एक ट्यूपल (विशेष रूप से, दो फ्लोट) पास करने की आवश्यकता होती है। पोस्ट-ऑर्डर ट्रैवर्सल पर, प्रत्येक नोड को स्वतंत्र रूप से तब तक संसाधित किया जा सकता है जब तक कि इसके सभी सबट्री (यदि कोई हों) पहले ही संसाधित हो चुके हैं। प्रसंस्करण के बाद, प्रत्येक नोड को अपने माता-पिता को एक ही फ्लोट पास करने की आवश्यकता होती है।

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

प्रत्येक नोड पर गणना की तीव्रता पेड़ में समान है। प्रत्येक नोड पर गणना छोटी है: नोड्स पर बच्चों की संख्या के बराबर लंबाई के साथ संख्याओं की एक सूची पर बस कुछ रकम और गुणा/विभाजित होते हैं।

पेड़ कार्रवाई की जा रही असंतुलित कर रहे हैं: एक ठेठ नोड 2 पत्ते प्लस 0-6 अतिरिक्त बच्चे नोड्स होगा। इसलिए, पेड़ को अपेक्षाकृत संतुलित उपट्री के सेट में विभाजित करना गैर-स्पष्ट (मेरे लिए) है। इसके अलावा, पेड़ों को सभी उपलब्ध रैम का उपभोग करने के लिए डिज़ाइन किया गया है: बड़ा पेड़ जिसे मैं संसाधित कर सकता हूं, बेहतर।

मेरे धारावाहिक कार्यान्वयन प्रति सिर्फ मेरी छोटी परीक्षण पेड़ों पर सेकंड 1000 पुनरावृत्तियों के आदेश पर उपलब्ध हो जाता है; "असली" पेड़ के साथ, मुझे उम्मीद है कि यह परिमाण (या अधिक?) के क्रम से धीमा हो सकता है। यह देखते हुए कि एक स्वीकार्य परिणाम तक पहुंचने के लिए एल्गोरिदम को कम से कम 100 मिलियन पुनरावृत्तियों (संभवतः एक बिलियन तक) की आवश्यकता होती है, मैं एकाधिक कोर का लाभ उठाने के लिए एल्गोरिदम को समानांतर करना चाहता हूं। मुझे समांतर प्रोग्रामिंग के साथ शून्य अनुभव है।

क्या बनता है के लिए सिफारिश की पद्धति मेरे एल्गोरिथ्म की प्रकृति दिया जाता है?

+1

पहला कदम यह निर्धारित करने के लिए आपके एल्गोरिदम का विश्लेषण कर रहा है कि क्या, यदि कोई है, तो भागों एक दूसरे से स्वतंत्र हैं। इसकी शायद आवश्यकता होगी कि आप अपने एल्गोरिदम को निम्न स्तर पर निम्न स्तर पर मानें। –

+0

बिल्कुल किस तरह के पेड़ आप प्रसंस्करण कर रहे हैं, और आपको किस प्रकार के संचालन का समर्थन करने की आवश्यकता है? इससे पहले कि आप समानांतर पेड़ ट्रैवर्सल पर विचार करें, अपने आप से पूछें कि क्या आप बेहतर डेटा संरचना का उपयोग करके अपने पेड़ों को फिर से लिख सकते हैं या ओ (एन) ऑपरेशन को इसके बजाय ओ (लॉग एन) में सुधार सकते हैं। – Juliet

+0

क्या पेड़ के नोड्स के बीच कोई साझा डेटा है, या वे तर्कसंगत रूप से अलग हैं? मैं कुछ सभ्य सुझाव दे सकता हूं, लेकिन अधिक जानकारी से यह आसान हो जाएगा। – Novelocrat

उत्तर

3

pure functions से बना होने के लिए अपने एल्गोरिदम को फिर से लिखने का प्रयास करें। इसका मतलब है कि कोड का हर टुकड़ा अनिवार्य रूप से एक (छोटा) स्थिर कार्य होता है जिसमें वैश्विक चर या स्थैतिक चर पर निर्भरता नहीं होती है, और यह कि सभी डेटा को अपरिवर्तनीय माना जाता है --- परिवर्तन केवल प्रतियों के लिए किए जाते हैं --- और सभी कार्य केवल कुशलतापूर्वक होते हैं (नया) डेटा लौटकर राज्य ("मैनिपुलेट" शब्द की ढीली भावना में)।

यदि प्रत्येक कार्य referentially transparent है --- यह केवल इसके इनपुट की गणना करने के लिए अपने इनपुट (और कोई छिपी स्थिति) पर निर्भर करता है, और एक ही इनपुट के साथ प्रत्येक फ़ंक्शन कॉल हमेशा एक ही आउटपुट उत्पन्न करता है --- तो आप एल्गोरिदम समानांतर करने के लिए अच्छी स्थिति: चूंकि आपका कोड वैश्विक चर (या फ़ाइलों, सर्वर इत्यादि) को कभी भी म्यूट नहीं करता है।) एक फ़ंक्शन को सुरक्षित रूप से दोहराया जा सकता है (फ़ंक्शन के परिणाम को पुन: सम्मिलित करने के लिए) या पूरी तरह अनदेखा किया जा सकता है (भविष्य का कोड इस फ़ंक्शन के साइड इफेक्ट्स पर निर्भर करता है, इसलिए कॉल को पूरी तरह से छोड़ना कुछ भी नहीं तोड़ देगा)। फिर जब आप अपने कार्यों के सूट चलाते हैं (उदाहरण के लिए MapReduce, hadoop, आदि के कुछ कार्यान्वयन पर) कार्यों की श्रृंखला पूरी तरह से एक समारोह के आउटपुट और किसी अन्य फ़ंक्शन के इनपुट पर आधारित निर्भरताओं का जादुई कैस्केड का कारण बनती है, और WHAT आप गणना करने की कोशिश कर रहे हैं (शुद्ध कार्यों के माध्यम से) ओआरडीईआर से पूरी तरह से अलग होगा जिसमें आप इसकी गणना करने की कोशिश कर रहे हैं (एक प्रश्नपत्र के रूप में एक शेड्यूलर के कार्यान्वयन द्वारा उत्तर दिया गया प्रश्न)।

सोचने के तरीके को सीखने के लिए एक महान जगह प्रोग्रामिंग भाषा Haskell (या कुछ एफ # या ओकैम) में अपना एल्गोरिदम लिखना है, जिसमें बॉक्स के बाहर समानांतर/बहुआयामी प्रोग्रामिंग के लिए बहुत अच्छा समर्थन है। हास्केल आपके कोड को शुद्ध होने के लिए मजबूर करता है, इसलिए यदि आपका एल्गोरिदम काम करता है, तो यह शायद आसानी से समांतर है।

+0

यहां कुछ दिलचस्प विचार हैं। हास्केल दिलचस्प लग रहा है। अगर मैं वहां एल्गोरिदम को बंद करने के लिए सीखने का समय बिताता हूं, तो क्या मुझे मैपरेडस/हडूप सीखना होगा, या ये अपमानजनक दृष्टिकोण हैं? – travis

+1

हास्केल में रिकोडिंग मैपरेडस/हाडोप पर्यावरण में रिकोडिंग से अलग होगी। पसंद वास्तव में उस पेड़ के पैमाने पर निर्भर करता है जिसके साथ आप काम करने की कोशिश कर रहे हैं। – Novelocrat

+0

हास्केल सीखने के लिए थोड़ा दिमागी झुकाव है (एक अच्छे तरीके से)। सबसे अच्छी किताबों में से एक हाल ही में O'Reilly द्वारा प्रकाशित किया गया था और मुफ्त में ऑनलाइन उपलब्ध है: http: //book.realworldhaskell।संगठन/पढ़ने/अध्याय 24 समानांतर प्रोग्रामिंग के दृष्टिकोण के बारे में विस्तृत जानकारी देता है, मैपरेडस का उपयोग करके विशिष्ट उदाहरणों के साथ: http://book.realworldhaskell.org/read/concurrent-and-multicore-programming.html –

2

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

+2

सामान्य विधि मांग करती है कि प्रत्येक प्रोग्रामर कैटलॉग, धागे और साझा डेटा संरचनाओं में सबसे कठिन उपयोग करने वाली संरचनाओं में से दो के साथ समानांतर गति कार्य के लिए पूछता है। जैसे ही प्रोग्रामर एक साझा-मेमोरी मशीन से परे समांतरता को विस्तारित करना चाहता है, उसे अत्यधिक हुप्स के माध्यम से कूदने की भी आवश्यकता होगी। – Novelocrat

2

यह उत्तर बताता है कि मैं इसे समानांतर भाषा और रनटाइम सिस्टम के साथ कैसे करूं जो मैं दिन-प्रतिदिन Charm++ पर काम करता हूं। ध्यान दें कि इस ढांचे के भीतर अनुक्रमिक कोड के लिए उपयोग की जाने वाली भाषा सी या सी ++ है, इसलिए आपको कम्प्यूटेशनल कोड को पोर्ट करने में कुछ प्रयास करना होगा। आकर्षण ++ में पाइथन कोड के साथ इंटरऑपरेट करने के लिए कुछ तंत्र हैं, हालांकि मैं उन पहलुओं से कम परिचित हूं। यह संभव है कि आप पाइथन में ड्राइवर और इंटरफ़ेस कोड रख सकें और केवल C++ में भारी कम्प्यूटेशनल कोड डालें। भले ही, अनुक्रमिक कोड पर पोर्टिंग प्रयास से आपको प्रदर्शन की अगली वृद्धि में अच्छा लगेगा।

डिजाइन:

समानांतर वस्तुओं की एक सरणी बनाएँ (घर का काम हमारे वातावरण में कहा जाता है), और प्रत्येक कुछ सबट्री जड़ से शुरू होकर नीचे की ओर partways विस्तार आंतरिक पेड़ नोड्स के एक worklist आवंटित। उन नोड्स से जुड़ी कोई भी पत्तियां उस श्रृंखला से संबंधित होंगी।

प्रत्येक समानांतर वस्तु दो अतुल्यकालिक दूर invocable तरीकों, प्रविष्टि तरीकों, passDown(float a, float b) और passUp(int nodeID, float f) है, जो उन के बीच संचार के अंक होगा के रूप में जाना की आवश्यकता होगी। passDown प्री-ऑर्डर गणना करने के लिए जो भी नोड विधि का उपयोग किया जाता है, और उन नोड्स जिनमें ऑब्जेक्ट ऑफ ऑब्जेक्ट हैं, वे passDown उन वंशज वस्तुओं पर कॉल करेंगे।

एक बार सभी नीचे की ओर काम करने के बाद, वस्तु ऊपर की ओर अपने पत्तियों पर गणना करेगी और इसके वंशजों की प्रतीक्षा करेगी। passUp के आमंत्रण प्राप्त करने वाले ऑब्जेक्ट के पेड़ तक अब तक गणना करेंगे क्योंकि यह तब तक हो सकता है जब तक कि वह ऐसे माता-पिता को न मारता है जिसे अपने सभी बच्चों से डेटा प्राप्त नहीं हुआ है। जब ऑब्जेक्ट का रूट नोड ऊपर की ओर काम करता है, तो यह पैरेंट नोड धारण करने वाले ऑब्जेक्ट पर passUp पर कॉल करेगा। जब पूरे पेड़ की जड़ हो जाती है, तो आप जानते हैं कि एक पुनरावृत्ति पूरी हो गई है।

रनटाइम परिणाम:

इस बार लागू किया गया है, क्रम प्रणाली आप के लिए समानांतर निष्पादन संभालती है। यह प्रोसेसर के बीच वस्तुओं को वितरित करेगा, और यहां तक ​​कि अलग गणना नोड्स (इसलिए नाटकीय रूप से अपने पेड़ के आकार की छत को बढ़ा रहा है, क्योंकि आपकी उपलब्ध स्मृति बहुत अधिक हो सकती है)। प्रोसेसर और नोड्स में संचार इन-प्रोसेस संचार की तरह दिखता है - एसिंक्रोनस विधि कॉल। रनटाइम आपके सभी प्रोसेसर को यथासंभव प्रत्येक पुनरावृत्ति में व्यस्त रखने के लिए ऑब्जेक्ट्स को लोड-बैलेंस कर सकता है।

ट्यूनिंग:

आप इस तरह से जाने के लिए और ट्यूनिंग समानांतर प्रदर्शन की बात करने के लिए मिलता है, तो आप भी सेट कर सकते हैं संदेशों पर प्राथमिकताओं महत्वपूर्ण मार्ग की लंबाई कम रखने के लिए। मेरे सिर के ऊपर से, प्राथमिकता मेरा सुझाव था

  1. नीचे काम गैर शून्य
    • जड़ के करीब जैसे ही
  2. ऊपर की ओर काम चला जाता है कि इस क्रम में काम करना होगा
    • पत्तियों के करीब हो जाता है जैसे ही

आकर्षण ++ एक प्रदर्शन विश्लेषण उपकरण के साथ काम करता है जिसे अनुमान लगाया जाता है कि आपका प्रोग्राम कैसा प्रदर्शन कर रहा है, इस बारे में और जानकारी प्राप्त करने के लिए।

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