पायथन मल्टीप्रोसेसिंग: `चंक्साइज़` के पीछे तर्क को समझना


84

क्या कारकों chunksizeजैसे तरीकों के लिए एक इष्टतम तर्क निर्धारित करते हैं multiprocessing.Pool.map()? यह .map()विधि अपने डिफ़ॉल्ट चंकाइज़ (नीचे समझाया गया) के लिए एक मनमाने ढंग से उपयोग करने के लिए लगता है; उस विकल्प को क्या प्रेरित करता है और क्या कुछ विशेष स्थिति / सेटअप के आधार पर अधिक विचारशील दृष्टिकोण है?

उदाहरण - कहो कि मैं हूँ:

  • एक पासिंग iterableके लिए .map()कि है ~ 15 मिलियन तत्वों;
  • 24 कोर के साथ एक मशीन पर काम करना और processes = os.cpu_count()भीतर डिफ़ॉल्ट का उपयोग करना multiprocessing.Pool()

मेरी भोली सोच 24 कर्मचारियों में से प्रत्येक को एक समान आकार का हिस्सा देने का है, यानी 15_000_000 / 24625,000। सभी श्रमिकों का पूरी तरह से उपयोग करते हुए बड़ी मात्रा में टर्नओवर / ओवरहेड को कम करना चाहिए। लेकिन ऐसा लगता है कि यह प्रत्येक कार्यकर्ता को बड़े बैच देने की कुछ संभावित गिरावट को याद कर रहा है। क्या यह अधूरी तस्वीर है, और मुझे क्या याद आ रहा है?


मेरे प्रश्न का एक हिस्सा इसके लिए डिफ़ॉल्ट तर्क से उपजा है chunksize=None: दोनों .map()और .starmap()कॉल .map_async(), जो इस तरह दिखता है:

def _map_async(self, func, iterable, mapper, chunksize=None, callback=None,
               error_callback=None):
    # ... (materialize `iterable` to list if it's an iterator)
    if chunksize is None:
        chunksize, extra = divmod(len(iterable), len(self._pool) * 4)  # ????
        if extra:
            chunksize += 1
    if len(iterable) == 0:
        chunksize = 0

इसके पीछे क्या तर्क है divmod(len(iterable), len(self._pool) * 4)? इसका तात्पर्य यह है कि चंक्साइज़ करीब होगा 15_000_000 / (24 * 4) == 156_250len(self._pool)4 से गुणा करने का इरादा क्या है ?

यह ऊपर से मेरे "भोले तर्क" की तुलना में 4 गुना छोटे कारक को बनाता है , जिसमें केवल श्रमिकों की संख्या से चलने योग्य की लंबाई को विभाजित करना शामिल है pool._pool

अंत में, पायथन डॉक्स से यह स्निपेट भी है .imap()जो आगे मेरी जिज्ञासा को बढ़ाता है:

chunksizeतर्क के द्वारा प्रयोग किया वैसा ही है जैसा map() विधि। बहुत लंबे चलने के लिए एक बड़े मूल्य का उपयोग करने वाले 1 के डिफ़ॉल्ट मान का उपयोग करने की तुलना chunksizeमें काम को बहुत तेजी से पूरा कर सकते हैं ।


संबंधित उत्तर जो सहायक है, लेकिन थोड़ा बहुत उच्च-स्तर: पायथन मल्टीप्रोसेसिंग: बड़े आकार के धीमे क्यों हैं?


1
4मनमाना है और सारथी की पूरी गणना एक अनुमान है। प्रासंगिक कारक यह है कि आपका वास्तविक प्रसंस्करण समय कितना भिन्न हो सकता है। इस पर थोड़ा और यहाँ जब तक मेरे पास एक जवाब के लिए समय है अगर अभी भी ज़रूरत है तो।
डार्कनॉट

क्या आपने इस प्रश्न की जाँच की है ?
एंड्रयू नागुइब

1
धन्यवाद @AndrewNaguib, मैं वास्तव में किसी भी तरह से ठोकर नहीं खाई थी
ब्रैड सोलोमन

1
बस आपको पता होना चाहिए: मैं इस सवाल को नहीं भूलता। वास्तव में, मैं उस दिन से बाइबिल के आयामों (बहुत उपयोगी कोड स्निपेट और फैंसी ग्राफिक्स) के एक विहित जवाब पर काम कर रहा हूं। इनाम अभी भी 1-2 सप्ताह पहले ही आ गया था, लेकिन यह पूरा हो गया है, लेकिन मुझे विश्वास है कि मैं समय सीमा से पहले कुछ बंद कर पाऊंगा।
Darkonaut

@ ब्रैडसोलोमन आपका स्वागत है :)। क्या यह आपके प्रश्न का उत्तर देता है?
एंड्रयू नागुइब

जवाबों:


194

संक्षिप्त जवाब

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

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

"यह जानना अच्छा है" आप सोच सकते हैं, "लेकिन यह जानने से मुझे अपनी ठोस बहुउद्देशीय समस्याओं के साथ कैसे मदद मिलती है?" खैर, यह नहीं है। अधिक ईमानदार लघु उत्तर है, "कोई संक्षिप्त उत्तर नहीं है", "बहुसंकेतन जटिल है" और "यह निर्भर करता है"। एक मनाया गया लक्षण अलग-अलग जड़ें हो सकता है, यहां तक ​​कि समान परिदृश्यों के लिए भी।

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


विषय - सूची

भाग I

  1. परिभाषाएं
  2. समानांतरकरण लक्ष्य
  3. समानांतरकरण परिदृश्य
  4. चुस्कियों का जोखिम> १
  5. पूल का चंक्साइज़-एल्गोरिथम
  6. एल्गोरिथ्म क्षमता को बढ़ाता है

    6.1 मॉडल

    ६.२ समानांतर अनुसूची

    6.3 दक्षता

    6.3.1 पूर्ण वितरण क्षमता (ADE)

    6.3.2 सापेक्ष वितरण दक्षता (RDE)

भाग द्वितीय

  1. Naive बनाम पूल का हिस्सा आकार-एल्गोरिथम
  2. वास्तविकता की जांच
  3. निष्कर्ष

पहले कुछ महत्वपूर्ण शब्दों को स्पष्ट करना आवश्यक है।


1 कई। परिभाषाएं


टुकड़ा

यहाँ एक हिस्सा iterableएक पूल विधि कॉल में निर्दिष्ट -argument का हिस्सा है । चंक्साइज़ की गणना कैसे की जाती है और इसके क्या प्रभाव हो सकते हैं, इस उत्तर का विषय है।


टास्क

डेटा के संदर्भ में एक कार्यकर्ता-प्रक्रिया में एक कार्य का भौतिक प्रतिनिधित्व नीचे दिए गए आंकड़े में देखा जा सकता है।

आकृति ०

यह आंकड़ा एक उदाहरण कॉल को दिखाता है pool.map(), जो multiprocessing.pool.workerफ़ंक्शन से ली गई कोड की एक पंक्ति के साथ प्रदर्शित होता है , जहां एक कार्य inqueueअनपैक हो जाता है। पूल-कार्यकर्ता-प्रक्रिया workerमें अंतर्निहित मुख्य कार्य MainThreadहै। func-Argument पूल-विधि में विनिर्दिष्ट केवल से मेल खाएगी func-variable अंदर workerकी तरह एकल कॉल तरीकों के लिए समारोह apply_asyncऔर के लिए imapके साथ chunksize=1। पूल-विधियों के बाकी हिस्सों के लिए एक-- chunksizeपैरामीटर के साथ प्रसंस्करण-फ़ंक्शन funcएक मैपर-फ़ंक्शन ( mapstarया starmapstar) होगा। यह फ़ंक्शन उपयोगकर्ता के निर्दिष्ट func-रूपक को मैप करता है जो चलने योग्य (-> "मानचित्र-कार्य") के संचरित चंक के हर तत्व पर है। यह समय, एक कार्य को परिभाषित करता है एक रूप में भीकाम की इकाई


टास्केल

जबकि एक चंक के पूरे प्रसंस्करण के लिए "कार्य" शब्द का उपयोग कोड के भीतर से मेल खाता है multiprocessing.pool, इस बात का कोई संकेत नहीं है कि तर्क के रूप में ठग के एक तत्व के साथ उपयोगकर्ता द्वारा निर्दिष्ट एक एकल कॉल कैसे funcहोना चाहिए। करने के लिए भेजा। नामकरण संघर्ष ( maxtasksperchildपूल के __init__-method के लिए -parameter) से उभरने वाले भ्रम से बचने के लिए , यह उत्तर कार्य की एकल इकाइयों को कार्य के रूप में संदर्भित करेगा

एक टास्केल ( कार्य + एल ement से) एक कार्य के भीतर काम की सबसे छोटी इकाई है । यह func-Method के पैरामीटर के साथ निर्दिष्ट फ़ंक्शन का एकल निष्पादन है Pool, जिसे प्रेषित चंक के एक तत्व से प्राप्त तर्कों के साथ कहा जाता है । एक कार्य में टास्कल्स होते हैं ।chunksize


समानांतरकरण ओवरहेड (पीओ)

पीओ में अंतर-प्रक्रिया संचार (आईपीसी) के लिए पायथन-आंतरिक ओवरहेड और ओवरहेड शामिल हैं। पायथन के भीतर प्रति-कार्य ओवरहेड पैकेजिंग के लिए आवश्यक कोड और कार्यों और इसके परिणामों को अनपैक करने के साथ आता है। IPC- ओवरहेड थ्रेड्स के आवश्यक सिंक्रनाइज़ेशन और विभिन्न एड्रेस स्पेस (दो कॉपी स्टेप्स: पेरेंट -> कतार -> चाइल्ड) के बीच डेटा की प्रतिलिपि के साथ आता है। IPC- ओवरहेड की राशि OS-, हार्डवेयर- और डेटा-आकार पर निर्भर है, जो प्रभाव के बारे में सामान्यीकरण को मुश्किल बनाता है।


2. समानांतर लक्ष्य

मल्टीप्रोसेसिंग का उपयोग करते समय, हमारा कुल लक्ष्य (स्पष्ट रूप से) सभी कार्यों के लिए कुल प्रसंस्करण समय को कम करना है। इस समग्र लक्ष्य तक पहुँचने के लिए, हमारे तकनीकी लक्ष्य किए जाने की आवश्यकता हार्डवेयर संसाधनों के उपयोग का अनुकूलन

तकनीकी लक्ष्य प्राप्त करने के लिए कुछ महत्वपूर्ण उप-लक्ष्य हैं:

  • समांतरन ओवरहेड को कम करें (सबसे प्रसिद्ध, लेकिन अकेले नहीं: IPC )
  • सभी सीपीयू-कोर के पार उच्च उपयोग
  • ओएस को अत्यधिक पेजिंग ( ट्रैशिंग ) से रोकने के लिए मेमोरी का उपयोग सीमित रखना

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


3. समानांतरकरण परिदृश्य

मल्टीप्रोसेसिंग।पूल.मैप () जैसे तरीकों के लिए कौन से कारक एक इष्टतम हिस्सा तर्क निर्धारित करते हैं

प्रश्न में प्रमुख कारक यह है कि हमारे एकल कार्यक्षेत्र में गणना का समय कितना भिन्न हो सकता है । इसे नाम देने के लिए, एक इष्टतम हिस्सा के लिए विकल्प प्रति कार्य समय के लिए अभिकलन समय के लिए भिन्नता ( CV ) के गुणांक द्वारा निर्धारित किया जाता है।

एक पैमाने पर दो चरम परिदृश्य, इस भिन्नता की सीमा से निम्नलिखित हैं:

  1. सभी टास्कल्स को समान गणना समय की आवश्यकता होती है।
  2. एक कार्यस्थल को समाप्त होने में सेकंड या दिन लग सकते हैं।

बेहतर यादगार के लिए, मैं इन परिदृश्यों का उल्लेख करूंगा:

  1. घना दृश्य
  2. विस्तृत परिदृश्य


घना दृश्य

एक में घने परिदृश्य यह एक बार में सभी taskels वितरित करने के लिए, कम से कम आवश्यक आईपीसी और संदर्भ स्विचिंग रखने के लिए वांछनीय होगा। इसका मतलब यह है कि हम केवल अधिक विखंडू बनाना चाहते हैं, क्योंकि वहां बहुत अधिक श्रमिक प्रक्रियाएं हैं। ऊपर पहले से ही बताया गया है, पीओ का वजन प्रति कार्य काल के हिसाब से कम होता है।

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


विस्तृत परिदृश्य

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

यदि Poolविधियां, डिफ़ॉल्ट रूप से, घने परिदृश्य के लिए पूरी तरह से अनुकूलित की जाएंगी, तो वे व्यापक परिदृश्य के करीब स्थित हर समस्या के लिए उप-कालिक समय बनाएंगे।


4. चूजों का जोखिम> 1

विस्तृत परिदृश्य के इस सरल छद्म-कोड उदाहरण पर विचार करें , जो हम एक पूल-विधि में पारित करना चाहते हैं:

good_luck_iterable = [60, 60, 86400, 60, 86400, 60, 60, 84600]

वास्तविक मूल्यों के बजाय, हम केवल 1 मिनट या 1 दिन की सादगी के लिए सेकंड में आवश्यक गणना समय देखने का नाटक करते हैं। हम मानते हैं कि पूल में चार कार्यकर्ता प्रक्रियाएं हैं (चार कोर पर) और इसके chunksizeलिए निर्धारित है 2। क्योंकि आदेश रखा जाएगा, कार्यकर्ताओं को भेजना ये होगा:

[(60, 60), (86400, 60), (86400, 60), (60, 84600)]

चूंकि हमारे पास पर्याप्त श्रमिक हैं और गणना का समय पर्याप्त है, इसलिए हम कह सकते हैं कि प्रत्येक श्रमिक प्रक्रिया को पहली जगह पर काम करने का एक हिस्सा मिलेगा। (यह तेजी से पूरा होने वाले कार्यों के लिए मामला नहीं है)। आगे हम कह सकते हैं, पूरे प्रसंस्करण में लगभग 86400 + 60 सेकंड लगेंगे, क्योंकि इस कृत्रिम परिदृश्य में एक चंक के लिए उच्चतम कुल गणना समय है और हम केवल एक बार ही विखंडन वितरित करते हैं।

अब इस पुनरावृत्ति पर विचार करें, जिसमें पिछले पुनरावृत्ति की तुलना में केवल एक ही तत्व अपनी स्थिति को बदल रहा है:

bad_luck_iterable = [60, 60, 86400, 86400, 60, 60, 60, 84600]

... और इसी क्रम:

[(60, 60), (86400, 86400), (60, 60), (60, 84600)]

हमारी कुल प्रसंस्करण के समय में लगभग दुगुनी (86400 + 86400) की छँटाई के साथ बस दुर्भाग्य! शातिर (86400, 86400) पाने वाला कार्यकर्ता अपने कार्य में दूसरे भारी टास्केल को रोक रहा है, जो कि पहले से ही समाप्त हो चुके एक कर्मचारी को (60, 60) के साथ वितरित किया जा रहा है। यदि हम सेट करते हैं तो हम स्पष्ट रूप से इस तरह के अप्रिय परिणाम को जोखिम में नहीं डालेंगे chunksize=1

यह बड़ा हिस्सा है। उच्च मात्रा के साथ हम कम ओवरहेड और ऊपर जैसे मामलों में शेड्यूलिंग लचीलेपन का व्यापार करते हैं, यह एक बुरा सौदा है।

हम अध्याय 6 में कैसे देखेंगे। एल्गोरिथ्म क्षमता को बढ़ाते हुए, बड़े आकार के चक्रव्यूह भी ड्यूरेटिव परिदृश्यों के लिए उप-परिणामी परिणाम पैदा कर सकते हैं ।


5. पूल का हिस्सा आकार-एल्गोरिथम

नीचे आपको स्रोत कोड के अंदर एल्गोरिथ्म का थोड़ा संशोधित संस्करण मिलेगा। जैसा कि आप देख सकते हैं, मैंने निचले हिस्से को काट दिया और एक फ़ंक्शन को chunksizeबाहरी रूप से तर्क की गणना के लिए लपेट दिया । मैंने 4एक factorपैरामीटर भी बदला और len()कॉल को आउटसोर्स किया ।

# mp_utils.py

def calc_chunksize(n_workers, len_iterable, factor=4):
    """Calculate chunksize argument for Pool-methods.

    Resembles source-code within `multiprocessing.pool.Pool._map_async`.
    """
    chunksize, extra = divmod(len_iterable, n_workers * factor)
    if extra:
        chunksize += 1
    return chunksize

यह सुनिश्चित करने के लिए कि हम सभी एक ही पृष्ठ पर हैं, यहाँ बताया गया divmodहै:

divmod(x, y)एक बिलिन फ़ंक्शन है जो लौटता है (x//y, x%y)x // yमंजिल विभाजन है, नीचे से गोल भागफल लौटाता है x / y, जबकि x % yमॉडुलो ऑपरेशन शेष से लौट रहा है x / y। इसलिए divmod(10, 3)रिटर्न (3, 1)

अब जब आप देखते हैं chunksize, extra = divmod(len_iterable, n_workers * 4), तो आप n_workersयहां देखेंगे कि बाद में आगे के समायोजन के बिना, yइन विभाजक x / yऔर गुणा है 4, इसके if extra: chunksize +=1बजाय प्रारंभिक रूप से कम से कम चार गुना छोटा (के लिए len_iterable >= n_workers * 4) होता है, अन्यथा।

4मध्यवर्ती चंक्साइज परिणाम पर गुणा के प्रभाव को देखने के लिए इस फ़ंक्शन पर विचार करें:

def compare_chunksizes(len_iterable, n_workers=4):
    """Calculate naive chunksize, Pool's stage-1 chunksize and the chunksize
    for Pool's complete algorithm. Return chunksizes and the real factors by
    which naive chunksizes are bigger.
    """
    cs_naive = len_iterable // n_workers or 1  # naive approach
    cs_pool1 = len_iterable // (n_workers * 4) or 1  # incomplete pool algo.
    cs_pool2 = calc_chunksize(n_workers, len_iterable)

    real_factor_pool1 = cs_naive / cs_pool1
    real_factor_pool2 = cs_naive / cs_pool2

    return cs_naive, cs_pool1, cs_pool2, real_factor_pool1, real_factor_pool2

ऊपर का फ़ंक्शन भोले chunksize ( cs_naive) और पूल के chunksize- एल्गोरिथ्म ( cs_pool1) के पहले चरण के साथ- साथ संपूर्ण पूल-एल्गोरिथ्म के लिए chunksize की गणना करता है cs_pool2। इसके अलावा यह वास्तविक कारकों की गणना करता हैrf_pool1 = cs_naive / cs_pool1 और rf_pool2 = cs_naive / cs_pool2, जो हमें बताता है कि पूल के आंतरिक संस्करण (ओं) की तुलना में कितनी बार भली भांति गणना की गई चुंकियां बड़ी हैं।

नीचे आप इस फ़ंक्शन से आउटपुट के साथ बनाए गए दो आंकड़े देखते हैं। बायां आंकड़ा सिर्फ n_workers=4एक लंबी लंबाई तक chunksizes दिखाता है 500। सही आंकड़ा के लिए मूल्यों को दर्शाता है rf_pool1। चलने योग्य लंबाई के लिए 16, वास्तविक कारक बन जाता है >=4(के लिए len_iterable >= n_workers * 4) और यह अधिकतम मूल्य 7चलने योग्य लंबाई के लिए है 28-31। यह मूल कारक से एक बड़े पैमाने पर विचलन है 4एल्गोरिथ्म अब पुनरावृत्तियों के लिए परिवर्तित करता है। यहां 'लंबा' सापेक्ष है और निर्दिष्ट श्रमिकों की संख्या पर निर्भर करता है।

आकृति 1

याद रखें कि cs_pool1अभी भी पूर्ण-एल्गोरिथ्म में निहित extraशेष से -सोल्डेमेंट में कमी है।divmodcs_pool2

एल्गोरिथ्म चलता है:

if extra:
    chunksize += 1

अब मामलों में थे वहाँ है एक शेष (एक extradivmod आपरेशन से), 1 से chunksize बढ़ती जाहिर है हर काम के लिए बाहर काम नहीं कर सकता। आखिरकार, अगर यह होता है, तो शुरू करने के लिए शेष नहीं होगा।

आप नीचे दिए गए आंकड़ों में कैसे देख सकते हैं, " अतिरिक्त-उपचार " का प्रभाव है, कि अभी के लिए वास्तविक कारक नीचे से rf_pool2परिवर्तित होता है और विचलन कुछ हद तक चिकना होता है। के लिए मानक विचलन और से बूंदों के लिए करने के लिए के लिए ।4 4n_workers=4len_iterable=5000.5233rf_pool10.4115rf_pool2

चित्र 2

आखिरकार, chunksize1 से बढ़ने का प्रभाव होता है, कि अंतिम कार्य केवल एक आकार का होता है len_iterable % chunksize or chunksize

अधिक दिलचस्प और हम बाद में कैसे देखेंगे, अधिक परिणामी, अतिरिक्त उपचार का प्रभाव हालांकि उत्पन्न चक्रों की संख्या के लिए मनाया जा सकता है ( n_chunks)। लंबे समय से चलने वाले पर्याप्त पुनरावृत्तियों के लिए, पूल के पूर्ण विखंडन-एल्गोरिथ्म ( n_pool2नीचे की आकृति में) पर विखंडू की संख्या को स्थिर करेगा n_chunks == n_workers * 4। इसके विपरीत, भोली एल्गोरिथ्म (एक प्रारंभिक burp के बाद) के बीच बारी-बारी से रहता है n_chunks == n_workersऔर n_chunks == n_workers + 1जैसे-जैसे चलने योग्य की लंबाई बढ़ती है।

चित्र तीन

नीचे आपको पूल और भोले चुंक-एल्गोरिथ्म के लिए दो संवर्धित जानकारी-फ़ंक्शन मिलेंगे। इन कार्यों के आउटपुट की आवश्यकता अगले अध्याय में होगी।

# mp_utils.py

from collections import namedtuple


Chunkinfo = namedtuple(
    'Chunkinfo', ['n_workers', 'len_iterable', 'n_chunks',
                  'chunksize', 'last_chunk']
)

def calc_chunksize_info(n_workers, len_iterable, factor=4):
    """Calculate chunksize numbers."""
    chunksize, extra = divmod(len_iterable, n_workers * factor)
    if extra:
        chunksize += 1
    # `+ (len_iterable % chunksize > 0)` exploits that `True == 1`
    n_chunks = len_iterable // chunksize + (len_iterable % chunksize > 0)
    # exploit `0 == False`
    last_chunk = len_iterable % chunksize or chunksize

    return Chunkinfo(
        n_workers, len_iterable, n_chunks, chunksize, last_chunk
    )

शायद अप्रत्याशित रूप से भ्रमित न हों calc_naive_chunksize_infoextraसे divmodchunksize गणना के लिए नहीं है।

def calc_naive_chunksize_info(n_workers, len_iterable):
    """Calculate naive chunksize numbers."""
    chunksize, extra = divmod(len_iterable, n_workers)
    if chunksize == 0:
        chunksize = 1
        n_chunks = extra
        last_chunk = chunksize
    else:
        n_chunks = len_iterable // chunksize + (len_iterable % chunksize > 0)
        last_chunk = len_iterable % chunksize or chunksize

    return Chunkinfo(
        n_workers, len_iterable, n_chunks, chunksize, last_chunk
    )

6. एल्गोरिथ्म क्षमता का परिमाण करना

अब, जब हमने देखा है कि Poolभोली एल्गोरिथ्म से आउटपुट की तुलना में अलग-अलग आकार का एल्गोरिथ्म कैसे दिखता है ...

  • कैसे बताएं कि क्या पूल का दृष्टिकोण वास्तव में कुछ सुधार करता है?
  • और क्या वास्तव में यह कुछ हो सकता है?

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

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

जब आप अध्याय 2 से समानांतरकरण लक्ष्यों को याद करते हैं , तो एक बुलेट-पॉइंट था:

  • सभी सीपीयू-कोर के पार उच्च उपयोग

पहले से उल्लेखित कुछ , पूल के चंकाइज़-एल्गोरिथ्म में सुधार करने की कोशिश की जा सकती है, यह आइडलिंग वर्कर-प्रक्रियाओं का न्यूनतमकरण है , क्रमशः सीपीयू-कोर का उपयोग

एसओ के बारे multiprocessing.Poolमें एक दोहराए जाने वाले प्रश्न को लोग उन अप्रसन्न कोर / निष्क्रिय कार्यकर्ता-प्रक्रियाओं के बारे में सोचकर पूछते हैं, जहां आप सभी कार्यकर्ता-प्रक्रियाओं के व्यस्त होने की उम्मीद करते हैं। हालांकि, इसके कई कारण हो सकते हैं, एक गणना के अंत में काम करने वाले कर्मचारी-प्रक्रियाएं एक अवलोकन हैं जो हम अक्सर कर सकते हैं, यहां तक कि उन मामलों में जहां पर श्रमिकों की संख्या एक विभाजक नहीं है , घने परिदृश्यों (प्रति कार्य काल के बराबर गणना) के साथ। का हिस्सा ( )।n_chunks % n_workers > 0

अब सवाल यह है:

हम व्यावहारिक रूप से किसी चीज में हमारी समझ का अनुवाद कैसे कर सकते हैं जो हमें देखे गए कार्यकर्ता-उपयोग की व्याख्या करने में सक्षम बनाता है, या उस संबंध में विभिन्न एल्गोरिदम की दक्षता की तुलना भी करता है?


6.1 मॉडल

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

चित्र 4

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

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


6.2 समानांतर अनुसूची (PS)

समानांतर अनुसूची समानांतर गणना, और y- अक्ष जहां x- अक्ष समय का प्रतिनिधित्व करता है एक दो आयामी प्रतिनिधित्व है समानांतर कार्यकर्ताओं का एक पूल का प्रतिनिधित्व करता है। श्रमिकों की संख्या और कुल गणना समय एक आयत के विस्तार को चिह्नित करते हैं, जिसमें छोटी आयतें खींची जाती हैं। ये छोटी आयतें कार्य (कार्य) की परमाणु इकाइयों का प्रतिनिधित्व करती हैं।

नीचे आप घने परिदृश्य के लिए पूल के चंकज-एल्गोरिदम के डीएम से डेटा के साथ खींचे गए पीएस के दृश्य का पता लगाते हैं ।

चित्र 5

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

नीचे के चित्र में तैयार किए गए भागों के नाम देखे जा सकते हैं।

चित्र 6

एक ओएम सहित एक पूर्ण पीएम में , आइडलिंग शेयर केवल पूंछ तक ही सीमित नहीं है, बल्कि कार्यों के बीच और यहां तक ​​कि टास्कल्स के बीच भी जगह है।


6.3 दक्षता

ऊपर पेश किए गए मॉडल कार्यकर्ता-उपयोग की दर को निर्धारित करते हैं। हम भेद कर सकते हैं:

  • वितरण क्षमता (डीई) - एक डीएम (या घने परिदृश्य के लिए एक सरल विधि ) की मदद से गणना की जाती है ।
  • समानांतरकरण दक्षता (पीई) - या तो एक कैलिब्रेटेड पीएम (भविष्यवाणी) की मदद से गणना की जाती है या वास्तविक गणनाओं के मेटा-डेटा से गणना की जाती है।

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

उपर्युक्त सभी क्षमताएँ मूल रूप से विभाजन व्यस्त भाग / समानांतर अनुसूची के भाग की गणना करके प्राप्त की जाती हैं । डीई और पीई के बीच अंतर ओवरहेड-विस्तारित पीएम के लिए समग्र समानांतर अनुसूची के एक छोटे हिस्से पर कब्जा करने वाले व्यस्त शेयर के साथ आता है ।

यह उत्तर आगे केवल घने परिदृश्य के लिए DE की गणना करने के लिए एक सरल विधि पर चर्चा करेगा । यह पर्याप्त रूप से विभिन्न विखंडू-एल्गोरिदम की तुलना करने के लिए पर्याप्त है, क्योंकि ...

  1. ... डीएम पीएम का वह हिस्सा है , जो अलग-अलग चॉन्केज-एल्गोरिदम के साथ बदलता है।
  2. ... कार्यस्थल प्रति समान गणना अवधि वाले घने परिदृश्य को "स्थिर स्थिति" दर्शाया गया है, जिसके लिए ये समय समीकरण से बाहर हो जाते हैं। किसी भी अन्य परिदृश्य सिर्फ यादृच्छिक परिणाम के लिए नेतृत्व करेंगे क्योंकि टास्कल्स का आदेश मायने रखता है।

6.3.1 पूर्ण वितरण क्षमता (ADE)

समांतर अनुसूची की पूरी क्षमता के माध्यम से व्यस्त शेयर को विभाजित करके सामान्य रूप से इस बुनियादी दक्षता की गणना की जा सकती है :

पूर्ण वितरण क्षमता (ADE) = व्यस्त शेयर / समानांतर अनुसूची

के लिए घने परिदृश्य , सरलीकृत गणना-कोड इस तरह दिखता है:

# mp_utils.py

def calc_ade(n_workers, len_iterable, n_chunks, chunksize, last_chunk):
    """Calculate Absolute Distribution Efficiency (ADE).

    `len_iterable` is not used, but contained to keep a consistent signature
    with `calc_rde`.
    """
    if n_workers == 1:
        return 1

    potential = (
        ((n_chunks // n_workers + (n_chunks % n_workers > 1)) * chunksize)
        + (n_chunks % n_workers == 1) * last_chunk
    ) * n_workers

    n_full_chunks = n_chunks - (chunksize > last_chunk)
    taskels_in_regular_chunks = n_full_chunks * chunksize
    real = taskels_in_regular_chunks + (chunksize > last_chunk) * last_chunk
    ade = real / potential

    return ade

यदि कोई सुस्ती शेयर , व्यस्त शेयर हो जाएगा बराबर करने के लिए अनुसूची समानांतर , इसलिए हम एक मिल एडीई 100% की। हमारे सरलीकृत मॉडल में, यह एक ऐसा परिदृश्य है जहां सभी उपलब्ध प्रक्रियाएं सभी कार्यों को संसाधित करने के लिए आवश्यक पूरे समय में व्यस्त रहेंगी। दूसरे शब्दों में, पूरी नौकरी प्रभावी रूप से 100 प्रतिशत के बराबर हो जाती है।

लेकिन कारण है कि मैं की बात कर रख कर पीई के रूप में पूर्ण पीई यहाँ?

यह समझने के लिए कि, हमें चकबंदी (सीएस) के लिए एक संभावित मामले पर विचार करना होगा जो अधिकतम समय-निर्धारण लचीलापन सुनिश्चित करता है (साथ ही, वहाँ के हाइलैंडर्स की संख्या भी हो सकती है? संयोग?)।

__________________________________ ~ एक ~ __________________________________

यदि हम, उदाहरण के लिए, चार कार्यकर्ता-प्रक्रियाएं और 37 कार्यस्थल हैं, तो भी निष्क्रिय श्रमिक होंगे chunksize=1, सिर्फ इसलिए n_workers=4कि 37 का विभाजक नहीं है। 37/4 को विभाजित करने का शेष 1 है। इस एकल शेष कार्य को पूरा करना होगा एक एकमात्र कार्यकर्ता द्वारा संसाधित किया गया, जबकि शेष तीन बेकार हैं।

इसी तरह, 39 कार्यकलापों के साथ अभी भी एक बेकार कर्मचारी होगा, आप नीचे चित्रित कैसे देख सकते हैं।

चित्र 7

जब आप ऊपरी तुलना समानांतर अनुसूची के लिए chunksize=1के लिए संस्करण नीचे के साथ chunksize=3, आप देखेंगे कि ऊपरी समानांतर अनुसूची छोटा होता है, पर समय कम X- अक्ष। अब यह स्पष्ट हो जाना चाहिए कि अप्रत्याशित रूप से कितना बड़ा हिस्सा , घने परिदृश्य के लिए भी समग्र गणना समय में वृद्धि कर सकता है

लेकिन दक्षता गणना के लिए सिर्फ एक्स-एक्सिस की लंबाई का उपयोग क्यों नहीं किया जाता है?

क्योंकि इस मॉडल में ओवरहेड निहित नहीं है। यह दोनों चक्रों के लिए अलग-अलग होगा, इसलिए एक्स-अक्ष वास्तव में सीधे तुलनीय नहीं है। ओवरहेड अभी भी एक लंबी कुल गणना समय की ओर ले जा सकता है जैसे नीचे दिए गए आंकड़े से केस 2 में दिखाया गया है ।

आंकड़ा 8


6.3.2 सापेक्ष वितरण दक्षता (RDE)

एडीई मूल्य जानकारी नहीं होती है, तो एक बेहतर taskels के वितरण 1. chunksize सेट के साथ संभव है बेहतर यहाँ अभी भी एक छोटे मतलब है सुस्ती शेयर

एक प्राप्त करने के लिए डे अधिकतम संभव के लिए समायोजित मूल्य डे , हम माना विभाजित करने के लिए है एडीई के माध्यम से एडीई हम के लिए मिलता है chunksize=1

सापेक्ष वितरण क्षमता (RDE) = ADE_cs_x / ADE_cs_1

इस प्रकार यह कोड में दिखता है:

# mp_utils.py

def calc_rde(n_workers, len_iterable, n_chunks, chunksize, last_chunk):
    """Calculate Relative Distribution Efficiency (RDE)."""
    ade_cs1 = calc_ade(
        n_workers, len_iterable, n_chunks=len_iterable,
        chunksize=1, last_chunk=1
    )
    ade = calc_ade(n_workers, len_iterable, n_chunks, chunksize, last_chunk)
    rde = ade / ade_cs1

    return rde

RDE , यहाँ कैसे परिभाषित किया गया है, संक्षेप में एक समानांतर अनुसूची की पूंछ के बारे में एक कहानी है । RDE पूंछ में निहित अधिकतम प्रभावी विखंडू से प्रभावित होता है। (यह पूंछ एक्स-एक्सिस लंबाई की हो सकती है chunksizeया last_chunk।) इसका परिणाम यह है, कि RDE स्वाभाविक रूप से "टेल-लुक" के सभी प्रकारों के लिए 100% (यहां तक) में परिवर्तित हो जाता है, जैसे नीचे की आकृति में दिखाया गया है।

आंकड़ा 9

एक कम RDE ...

  • अनुकूलन क्षमता के लिए एक मजबूत संकेत है।
  • स्वाभाविक रूप से अब पुनरावृत्तियों के लिए कम संभावना है, क्योंकि समग्र समानांतर अनुसूची के सापेक्ष पूंछ-भाग सिकुड़ते हैं।

कृपया इस उत्तर के भाग II को यहाँ देखें


51
सबसे महाकाव्य जवाबों में से एक मैंने एसओ पर देखा है।
क्रिश्चियन लॉन्ग

4
ओह, यह आपका संक्षिप्त उत्तर था: पी
d_kennetz

1
लेकिन forreal .. यह एक उत्कृष्ट उत्तर है। मैंने भविष्य के मामलों के लिए प्रश्न को तारांकित किया है जहां मैं इसे बेहतर ढंग से समझना चाहता हूं। इसके माध्यम से स्किमिंग ने मुझे पहले से ही बहुत कुछ सिखाया! धन्यवाद
d_kennetz

2
@ L.Iridium आपका स्वागत है! मैं matplotlib जहां संभव हो और अन्यथा का उपयोग किया था ... LibreOffice कैल्क + पिंटा (मूल छवि संपादन)। हाँ, मुझे पता है ... लेकिन यह किसी भी तरह काम करता है। ;)
डार्कनॉट

2
एसओ पर देखी गई सामग्री की तालिका के साथ पहले उत्तर दें।
tly_alex

51

इस उत्तर के बारे में

यह उत्तर उपर्युक्त स्वीकृत उत्तर का भाग II है ।


7. Naive बनाम पूल का हिस्सा आकार-एल्गोरिथम

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

सीएस_4_50

सीएस_200_250

जैसा कि अध्याय में दिखाया गया है " 5. पूल का चंक्साइज़-एल्गोरिथ्म ", पूल के चंकाइज़-एल्गोरिथ्म के साथ चंक्स की संख्या n_chunks == n_workers * 4बड़े पर्याप्त पुनरावृत्तियों के लिए स्थिर हो जाएगी , जबकि यह भोली दृष्टिकोण के बीच n_chunks == n_workersऔर n_chunks == n_workers + 1साथ स्विच करती रहती है । भोली एल्गोरिथ्म के लिए लागू होता है: क्योंकि n_chunks % n_workers == 1के Trueलिए है n_chunks == n_workers + 1, एक नया खंड बनाया जाएगा जहां केवल एक ही कार्यकर्ता कार्यरत होगा।

Naive Chunksize-Algorithm:

आप सोच सकते हैं कि आपने एक ही संख्या में श्रमिकों के लिए कार्य बनाए हैं, लेकिन यह केवल उन मामलों के लिए सही होगा जहां कोई शेष नहीं है len_iterable / n_workers। अगर वहाँ है एक शेष है, वहाँ एक भी कार्यकर्ता के लिए केवल एक ही कार्य के साथ एक नया खंड हो जाएगा। उस समय आपकी गणना अब समानांतर नहीं होगी।

नीचे आप अध्याय 5 में दिखाए गए के समान आकृति देखते हैं, लेकिन खंडों की संख्या के बजाय अनुभागों की संख्या प्रदर्शित करते हैं। पूल के पूर्ण विखंडन-एल्गोरिथ्म ( n_pool2) के लिए, n_sectionsकुख्यात, कठोर कोडित कारक पर स्थिर होगा 4। भोली एल्गोरिथ्म के लिए, n_sectionsएक और दो के बीच वैकल्पिक होगा।

आंकड़ा 10

पूल के विखंडन-एल्गोरिथ्म के लिए, n_chunks = n_workers * 4पहले उल्लेख किए गए अतिरिक्त उपचार के माध्यम से स्थिरीकरण , यहां एक नए अनुभाग के निर्माण को रोकता है और आइडलिंग शेयर को लंबे समय तक चलने वाले पुनरावृत्तियों के लिए एक कार्यकर्ता तक सीमित रखता है । इतना ही नहीं, लेकिन एल्गोरिथ्म आइडलिंग शेयर के सापेक्ष आकार को सिकोड़ता रहेगा , जिससे आरडीई मूल्य 100% तक पहुंच जाएगा।

उदाहरण के लिए "बहुत लंबा" n_workers=4है len_iterable=210। इससे बराबर या उससे अधिक के पुनरावृत्तियों के लिए, आइडलिंग शेयर केवल एक कार्यकर्ता तक ही सीमित रहेगा, एक गुण जो मूल रूप 4से पहले स्थान पर चकबंदी-एल्गोरिथ्म में -multiplication के कारण खो गया है।

चित्र 11

भोले चंक्साइज़-एल्गोरिथ्म भी 100% की ओर परिवर्तित होता है, लेकिन यह इतना धीमा करता है। अभिसरण प्रभाव केवल इस तथ्य पर निर्भर करता है कि पूंछ का सापेक्ष भाग उन मामलों के लिए सिकुड़ जाता है जहां दो खंड होंगे। केवल एक नियोजित कर्मचारी के साथ यह पूंछ एक्स-एक्सिस लंबाई तक सीमित है n_workers - 1, जिसके लिए संभव अधिकतम शेष है len_iterable / n_workers

भोले और पूल के चंकाइज़-एल्गोरिथ्म के लिए वास्तविक आरडीई मूल्य कैसे भिन्न होते हैं?

नीचे आप पाते हैं कि दो हीटमैट्स आरडीई मान दिखाते हैं जो सभी चलने योग्य लंबाई के लिए 5000 तक होते हैं, सभी वर्कर्स की संख्या 2 से 100 तक होती है। रंग स्केल 0.5 से 1 (50% -100%) तक जाता है। आप बाएं हीटमैप में भोले एल्गोरिदम के लिए बहुत अधिक अंधेरे क्षेत्रों (कम आरडीई मान) को देखेंगे। इसके विपरीत, दाईं ओर स्थित पूल का चंकाइज़-एल्गोरिथ्म बहुत अधिक धूप वाली तस्वीर खींचता है।

आंकड़ा 12

निचले-बाएँ अंधेरे कोनों बनाम ऊपरी-दाएं उज्ज्वल कोनों के विकर्ण ढाल, फिर से "लंबे चलने योग्य" कहने के लिए श्रमिकों की संख्या पर निर्भरता दिखा रहा है।

प्रत्येक एल्गोरिथ्म के साथ यह कितना बुरा हो सकता है?

पूल के चंक्साइज़-एल्गोरिथ्म के साथ आरडीई का 81.25% मूल्य श्रमिकों की श्रेणी के लिए सबसे कम मूल्य है और ऊपर निर्दिष्ट चलने योग्य लंबाई:

आंकड़ा 13

भोले चंकजाइए-एल्गोरिदम के साथ, चीजें बहुत खराब हो सकती हैं। यहां सबसे कम परिकलित RDE 50.72% है। इस मामले में, गणना के समय का लगभग आधा हिस्सा केवल एक श्रमिक चल रहा है! तो, बाहर देखो, नाइट्स लैंडिंग के गर्व मालिकों । ;)

आंकड़ा 14


8. रियलिटी चेक

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

सेट अप

निम्नलिखित भूखंड सभी एक सरल, सीपीयू-बाउंड डमी-फ़ंक्शन के समानांतर निष्पादन से निपटते हैं, जिसे विभिन्न तर्कों के साथ कहा जाता है ताकि हम यह देख सकें कि कैसे खींचा समानांतर अनुसूची इनपुट मूल्यों की निर्भरता में भिन्न होती है। इस फ़ंक्शन के भीतर "काम" में एक सीमा वस्तु पर केवल पुनरावृत्ति होती है। जब हम बड़ी संख्या में पास होते हैं, तो यह पहले से ही एक कोर को व्यस्त रखने के लिए पर्याप्त है। वैकल्पिक रूप से फ़ंक्शन कुछ कार्य-विशिष्ट अतिरिक्त लेता है dataजो कि बस अपरिवर्तित वापस आ जाता है। चूंकि प्रत्येक कार्यस्थल में सटीक समान कार्य शामिल है, हम अभी भी यहां एक घने परिदृश्य के साथ काम कर रहे हैं।

फ़ंक्शन को एनएस-रिज़ॉल्यूशन (पायथन 3.7+) के साथ टाइमस्टैम्प लेने वाले आवरण के साथ सजाया गया है। टाइमस्टैम्प का उपयोग किसी कार्यस्थल के समय की गणना करने के लिए किया जाता है और इसलिए एक अनुभवजन्य समानांतर अनुसूची के ड्राइंग को सक्षम करता है।

@stamp_taskel
def busy_foo(i, it, data=None):
    """Dummy function for CPU-bound work."""
    for _ in range(int(it)):
        pass
    return i, data


def stamp_taskel(func):
    """Decorator for taking timestamps on start and end of decorated
    function execution.
    """
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time_ns()
        result = func(*args, **kwargs)
        end_time = time_ns()
        return (current_process().name, (start_time, end_time)), result
    return wrapper

पूल के स्टार्मैप विधि को भी इस तरह से सजाया गया है कि केवल स्टार्मैप-कॉल ही समयबद्ध है। इस कॉल का "प्रारंभ और" अंत "उत्पादित समानांतर अनुसूची के एक्स-अक्ष पर न्यूनतम और अधिकतम निर्धारित करता है।

हम इन चश्मे के साथ एक मशीन पर चार कार्यकर्ता प्रक्रियाओं पर 40 टास्कल्स की गणना का निरीक्षण करने जा रहे हैं: पायथन 3.7.1, उबंटू 18.04.2, Intel® Core ™ i7-2600K CPU @ 3.40GHz × 8

इनपुट मान जो विविध होंगे वे इन-लूप (30k, 30M, 600M) में पुनरावृत्तियों की संख्या हैं और इसके अतिरिक्त डेटा साइज (प्रति टास्कल, सुन्न- ndarray: 0 MiB, 50 MiB) भेजते हैं।

...
N_WORKERS = 4
LEN_ITERABLE = 40
ITERATIONS = 30e3  # 30e6, 600e6
DATA_MiB = 0  # 50

iterable = [
    # extra created data per taskel
    (i, ITERATIONS, np.arange(int(DATA_MiB * 2**20 / 8)))  # taskel args
    for i in range(LEN_ITERABLE)
]


with Pool(N_WORKERS) as pool:
    results = pool.starmap(busy_foo, iterable)

नीचे दिखाए गए रनों को चंक्स के समान क्रमबद्ध होने के लिए चुना गया था ताकि आप वितरण मॉडल से समानांतर अनुसूची की तुलना में अंतर को बेहतर ढंग से देख सकें, लेकिन उन आदेशों को न भूलें जिनमें श्रमिकों को उनके कार्य का निर्धारण गैर-नियतात्मक है।

डीएम की भविष्यवाणी

दोहराने के लिए, वितरण मॉडल "एक समानांतर अनुसूची" की भविष्यवाणी करता है जैसे कि हमने इसे अध्याय 6.2 में पहले ही देख लिया है:

आकृति १५

पहला आरयूएन: 30k पुनरावृत्तियों और प्रति टास्क में 0 MiB डेटा

चित्र 16

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

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

इसके अलावा आप देख सकते हैं कि इस तथ्य के बावजूद कि प्रत्येक कार्यस्थल में समान मात्रा में कार्य शामिल है, टास्कल के लिए वास्तविक मापा समय बहुत भिन्न होता है। कार्यकर्ता -3 और कार्यकर्ता -4 को वितरित किए गए कार्य को पहले दो श्रमिकों द्वारा संसाधित किए गए लोगों की तुलना में अधिक समय की आवश्यकता होती है। इस रन के लिए मुझे संदेह है कि यह उस समय कार्यकर्ता -3 / 4 के लिए टर्बो बूस्ट उपलब्ध नहीं होने के कारण है , इसलिए उन्होंने अपने कार्यों को कम घड़ी दर के साथ संसाधित किया।

पूरी गणना इतनी हल्की है कि हार्डवेयर या ओएस-शुरू की अराजकता-कारक पीएस को काफी हद तक तिरछा कर सकते हैं । गणना एक "हवा पर पत्ता" है और सैद्धांतिक रूप से फिटिंग परिदृश्य के लिए भी DM -prediction का बहुत कम महत्व है।

दूसरा आरयूएन: 30 एम पुनरावृत्तियों और 0 एमईबी डेटा प्रति कार्यस्थल

चित्र 17

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

3 आरयूएन: 30 एम पुनरावृत्तियों और प्रति टास्क में 50 मिब डेटा

चित्र 18

30M पुनरावृत्तियों को रखते हुए, लेकिन इसके अलावा कार्यस्थल पर आगे और पीछे फिर से चित्र को 50 MiB भेजना। यहाँ कतार-प्रभाव अच्छी तरह से दिखाई देता है। वर्कर -1 की तुलना में वर्कर -4 को अपने दूसरे कार्य के लिए अधिक समय तक इंतजार करने की जरूरत है। अब 70 श्रमिकों के साथ इस अनुसूची की कल्पना करें!

यदि कार्यस्थल कम्प्यूटेशनल रूप से बहुत हल्का होता है, लेकिन पेलोड के रूप में एक उल्लेखनीय मात्रा में डेटा खर्च करता है, तो एकल साझा कतार की अड़चन पूल में अधिक श्रमिकों को जोड़ने के किसी भी अतिरिक्त लाभ को रोक सकती है, भले ही वे भौतिक पट्टियों द्वारा समर्थित हों। ऐसे मामले में, वर्कर -1 को अपने पहले कार्य के साथ किया जा सकता है और वर्कर -40 के पहले कार्य का इंतजार करने से पहले ही एक नए का इंतजार किया जा सकता है।

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

4th RUN: 600M पुनरावृत्तियों और प्रति टास्क में 50 MiB डेटा

आकृति १ ९

यहां हम 50 MiB फिर से भेजते हैं, लेकिन पुनरावृत्तियों की संख्या 30M से 600M तक बढ़ाते हैं, जो कुल गणना समय को 10 एस से 152 एस तक लाता है। फिर से तैयार की गई समानांतर अनुसूची , अनुमानित एक के साथ एक परिपूर्ण मैच के करीब है, डेटा कॉपी के माध्यम से ओवरहेड हाशिए पर है।


9. निष्कर्ष

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

जैसा कि यह जवाब उम्मीद से दिखाया गया है, पूल का हिस्सा-एल्गोरिथ्म भोले दृष्टिकोण की तुलना में औसतन बेहतर कोर उपयोग की ओर जाता है, कम से कम औसत मामले के लिए और जब तक ओवरहेड नहीं माना जाता है। यहाँ भोली एल्गोरिथ्म में डिस्ट्रीब्यूशन एफिशिएंसी (DE) ~ 51% तक कम हो सकती है, जबकि पूल के चंकाइज़ एल्गोरिथ्म में इसकी कम ~ ~ 81% है। DE में IPC की तरह समानांतरीकरण उपरि (पीओ) शामिल नहीं है। अध्याय 8 में दिखाया गया है कि डीए अभी भी हाशिये पर उपरि के साथ घने परिदृश्य के लिए महान भविष्य कहनेवाला शक्ति हो सकता है।

इस तथ्य के बावजूद कि पूल का चंक्साइज़-एल्गोरिथ्म भोले दृष्टिकोण की तुलना में एक उच्च डे प्राप्त करता है , यह हर इनपुट तारामंडल के लिए इष्टतम कार्यस्थल वितरण प्रदान नहीं करता है। हालांकि एक साधारण स्थैतिक चंकिंग-एल्गोरिथ्म (ओवरहेड-सहित) समानांतरीकरण दक्षता (PE) को ऑप्टिमाइज़ नहीं कर सकता है, कोई अंतर्निहित कारण नहीं है कि यह हमेशा 100% का एक सापेक्ष वितरण दक्षता (RDE) प्रदान नहीं कर सकता है, इसका मतलब है कि डीई के रूप में के साथ chunksize=1। एक सरल हिस्सा-एल्गोरिथ्म केवल मूल गणित के होते हैं और किसी भी तरह से "केक को काट" ​​करने के लिए स्वतंत्र हैं।

पूल के "समान-आकार-मंथन" एल्गोरिथ्म के कार्यान्वयन के विपरीत, "समान-आकार-मंथन" एल्गोरिथ्म प्रत्येक / संयोजन के लिए 100% का RDE प्रदान करेगा । पूल के स्रोत में लागू करने के लिए एक सम-आकार-रहित एल्गोरिथ्म थोड़ा अधिक जटिल होगा, लेकिन मौजूदा एल्गोरिथम के शीर्ष पर बस कार्यों को पैकेजिंग द्वारा संशोधित किया जा सकता है (मैं यहां से लिंक करता हूं कि मैं क्यू / ए को छोड़ देता हूं उसको कैसे करे)।len_iterablen_workers


6

मुझे लगता है कि जो कुछ आप याद कर रहे हैं उसका एक हिस्सा यह है कि आपका भोला अनुमान यह मानता है कि काम की प्रत्येक इकाई को उसी समय लगता है जिस स्थिति में आपकी रणनीति सबसे अच्छी होगी। लेकिन अगर कुछ नौकरियां दूसरों की तुलना में जल्दी खत्म हो जाती हैं, तो कुछ कोर धीमी नौकरियों के खत्म होने के इंतजार में बेकार हो सकते हैं।

इस प्रकार, विखंडू को 4 गुना अधिक टुकड़ों में तोड़कर, फिर यदि एक हिस्सा जल्दी खत्म हो जाता है, तो कोर अगले चंक को चालू कर सकता है (जबकि अन्य कोर अपने धीमे भाग पर काम करते हैं)।

मुझे नहीं पता कि उन्होंने कारक 4 को वास्तव में क्यों चुना है, लेकिन यह मानचित्र कोड के ओवरहेड को कम करने (जो सबसे बड़ा हिस्सा संभव है) के बीच एक व्यापार होगा और अलग-अलग मात्रा में बार-बार होने वाले विखंडन को संतुलित करेगा (जो सबसे छोटा हिस्सा संभव है ) है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.