क्या आप जानते हैं - अपने पायथन कोड को कैसे तेज़ी से चलाना है? (पहली किस्त)…

अंतिम ट्यूटोरियल में हमने आपको लाइन_प्रोफाइलर से पेश किया, एक पैकेज जो आपके कोड को प्रोफाइल करने में आपकी मदद कर सकता है। अब एक कदम आगे बढ़ाने का समय आ गया है।

डिड यू नो सीरीज़ के इस 4 के ट्यूटोरियल में, हम पायथन का उपयोग करके मल्टी-थ्रेडिंग और मल्टी-प्रोसेसिंग दृष्टिकोणों को लागू करने के बारे में सीखेंगे। ये दृष्टिकोण ऑपरेटिंग सिस्टम को गाइड करते हैं, ताकि सिस्टम हार्डवेयर का इष्टतम उपयोग किया जा सके और इसलिए कोड निष्पादन को कुशल बनाया जाए।

०.) उम्मीदें

कृपया ध्यान दें कि इस ट्यूटोरियल का उद्देश्य मल्टी-थ्रेडिंग और मल्टी-प्रोसेसिंग के उपयोग और लाभों को उजागर करना है।

मल्टी-थ्रेडिंग और मल्टी-प्रोसेसिंग के अलावा अन्य अवधारणाओं से संबंधित कोड के ब्लॉक के लिए, पाठक से अपेक्षा की जाती है कि वे या तो उन्हें जानें या अन्य ऑनलाइन संसाधनों को पढ़कर उन्हें समझें।

1.) मल्टी-थ्रेडिंग

क्वोटिंग विकी - कंप्यूटर आर्किटेक्चर में, मल्टी-थ्रेडिंग एक सेंट्रल प्रोसेसिंग यूनिट (सीपीयू) (या मल्टी-कोर प्रोसेसर में एक सिंगल कोर) की क्षमता है, जो कि ऑपरेटिंग सिस्टम द्वारा समर्थित समवर्ती रूप से निष्पादन के कई थ्रेड्स प्रदान करता है।

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

ए।) पायथन में मल्टी-थ्रेडिंग

"थ्रेडिंग", पायथन स्टैंडर्ड लाइब्रेरी मल्टी-थ्रेडिंग फ्रेमवर्क का समर्थन करता है। पुस्तकालय मानक पायथन इंस्टॉलेशन के साथ डिफ़ॉल्ट रूप से आता है और इसलिए इसे सीधे हमारे कोड में आयात किया जा सकता है।

मल्टी-थ्रेडिंग की प्रभावशीलता को प्रदर्शित करने के लिए, हम 5 चित्रों को अनप्लैश से डाउनलोड करेंगे। जब हम इन छवियों को क्रमिक रूप से डाउनलोड करते हैं तो हम निष्पादन समय का पालन करते हैं:

#### आयात अनुरोध पुस्तकालय आयात अनुरोध
#### फ़ंक्शन को परिभाषित करते हुए down_img (नाम, लिंक) को परिभाषित करें: डेटा = request.get (लिंक) .content नाम = f "/ home / isud / DidYouKnow / Tutorial 5 / {name} .jpg" खुले (नाम) से। "wb") फ़ाइल के रूप में: file.write (डेटा)
#### 5 चित्र क्रमिक रूप से %% timeit -n1 -r1 चित्र डाउनलोड किया गया = = '' https://images.unsplash.com/photo-1531458999205-f31f14fa217b ',' https://images.unsplash.com/photo-1488572749058 -7f52dd70e0fa ',' https://images.unsplash.com/photo-1531404610614-68f9e73e35db ',' https://images.unsplash.com/photo-15234405193-3884f5ca475f ',' https://images.unsplash.com ' / फोटो -1565098735462-5db3412ac4cb '] के लिए मैं, enumerate (images) में लिंक: down_img (i, लिंक)
#### %% समयित परिणाम 51.4 s s 0 ns प्रति लूप (मतलब d std। 1 रन का देवता, 1 लूप प्रत्येक)।

जैसा कि देखा जा सकता है, 5 छवियों के डाउनलोड में 51.4 सेकंड लगे जहां पिछले डाउनलोड के समाप्त होने के बाद ही एक नया डाउनलोड शुरू होता है। आइए अब देखते हैं कि मल्टी-थ्रेडिंग कोड के प्रदर्शन को कैसे बेहतर बना सकती है।

#### आयात अनुरोधों को आवश्यक लाइब्रेरी आयात आयात करना
#### फ़ंक्शन को परिभाषित करते हुए down_img (नाम, लिंक) को परिभाषित करें: डेटा = request.get (लिंक) .content नाम = f "/ home / isud / DidYouKnow / Tutorial 5 / {name} .jpg" खुले (नाम) से। "wb") फ़ाइल के रूप में: file.write (डेटा)
#### समानांतर धागे में डाउनलोड की गई छवियाँ %% timeit -n1 -r1 धागे = [] चित्र = ['https://images.unsplash.com/photo-1531458999205-f31f14fa217b', 'https: //images.unsplash'। com / photo-1488572749058-7f52dd70e0fa ',' https://images.unsplash.com/photo-1531404610614-68f9e73e35db ',' https://images.unsplash.com/photo-1523489405193-3884f5ca475f ',' https ' images.unsplash.com/photo-1565098735462-5db3412ac4cb '] i के लिए, enumerate (images) में लिंक: t = thread.Thread (target = down_img, args = (i, link)) t.start () threads.append (() टी)
धागे में धागे के लिए: thread.join ()
#### %% समयित परिणाम 25.6 s n 0 ns प्रति लूप (मतलब d std। 1 रन का देवता, 1 लूप प्रत्येक)।

कोड समझाया - छवि डाउनलोड लूप को परिभाषित करना:

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

क्यों शामिल होना आवश्यक है?

  • चरण 2 तक, हमारे सभी धागे (मुख्य धागा और समानांतर धागे) समानांतर में निष्पादित हो रहे थे। फ़ंक्शन कॉल को समानांतर थ्रेड्स में किया जाता है, फ़ंक्शन कॉल पूरा होने से पहले मुख्य थ्रेड निष्पादन को पूरा कर सकता है। इससे बचने के लिए, समानांतर धागे को मुख्य धागे से जोड़ा जाना चाहिए। यह सुनिश्चित करता है कि मुख्य धागा समानांतर धागे के पूरा होने के बाद ही पूरा होता है। इन 2 परिदृश्यों को नीचे दिए गए चित्र में दिखाया गया है:
बिना और जुड़ने के धागे
  • निष्पादन समय - जैसा कि देखा जा सकता है, छवियों को डाउनलोड करने का निष्पादन समय लगभग 50% (25.6 सेकंड लगभग) से नीचे चला गया है।

उपरोक्त उदाहरण से पता चलता है कि बहु-सूत्रण I / O संचालन में कैसे सहायक हो सकता है और डाउनलोड / अपलोड प्रक्रियाओं की दक्षता में सुधार कर सकता है।

2.) मल्टी प्रोसेसिंग

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

पायथन में मल्टी प्रोसेसिंग

"थ्रेडिंग" की तरह, "मल्टीप्रोसेसिंग" एक अन्य पुस्तकालय है, जिसका उपयोग पायथन में बहु-प्रसंस्करण सुविधा को सक्षम करने के लिए किया जाता है।

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

#### समय पुस्तकालय आयात समय आयात
#### फंक्शन डिफ डिफाइन_फ्यून्क (संख्या) को परिभाषित करना: i for रेंज (संख्या): a = i ** 2
#### रेंज में डेमो फ़ंक्शन क्रमिक रूप से %% timeit -n1 -r1 कॉलिंग के लिए (8): Demo_func (10000000)
#### %% समयित परिणाम 21.2 s s 0 ns प्रति लूप (मतलब d std। 1 रन का देवता, 1 लूप प्रत्येक)।

डेमो फ़ंक्शन के 8 अनुक्रमिक निष्पादन के लिए लिया गया समय (21.2 सेकंड) नोटिस करें। अब जब मल्टी प्रोसेसिंग सेटअप में यह किया जाता है तो प्रदर्शन के उत्थान की जाँच करें।

#### समय पुस्तकालय आयात समय आयात
#### फंक्शन डिफ डिफाइन_फ्यून्क (संख्या) को परिभाषित करना: i for रेंज (संख्या): a = i ** 2
#### मल्टी-प्रोसेसिंग डेमो फंक्शन %% timeit -n1 -r1 प्रक्रियाएं = [] lop_size = [10000000,10000000,10000000,10000000,10000000,10000000, 100000, p] बहुप्रोसेसरिंग। pool () p.map () Demo_func, lop_size) p.close () p.join ()
#### %% समयित परिणाम 11.6 s s 0 ns प्रति लूप (मतलब d std। 1 रन का देवता, 1 लूप प्रत्येक)।

निष्पादन समय में गिरावट को 50% (11.6 सेकंड) के करीब मानें। ये कैसे हुआ ? अनुक्रमिक प्रसंस्करण में, एक एकल सीपीयू कोर का उपयोग एक समय में किया जाता है जबकि बहु-प्रसंस्करण में, सभी सिस्टम कोर समानांतर में उपयोग किए जाते हैं। यह सीपीयू उपयोग स्क्रीन शॉट्स नीचे से देखा जा सकता है

अनुक्रमिक बनाम समानांतर निष्पादन

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

कोड स्पष्टीकरण

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

उपरोक्त परिदृश्य से, हम स्पष्ट रूप से देख सकते हैं कि कैसे बहु-प्रसंस्करण इन-कुशल कोड प्रदर्शनों के खिलाफ लड़ने के लिए एक महान हथियार हो सकता है।

नोट बंद करना

इस ट्यूटोरियल में, हमने अपने सिस्टम हार्डवेयर का इष्टतम उपयोग करके कोड प्रदर्शन को बेहतर बनाने पर अपना ध्यान केंद्रित रखा। अगली किस्त विशिष्ट प्रोग्रामिंग प्रथाओं पर ध्यान केंद्रित करेगी जो कोड प्रदर्शन में काफी सुधार दे सकती है।

मुझे उम्मीद है कि डिड यू नो सीरीज़ का यह ट्यूटोरियल जानकारीपूर्ण था और आपने कुछ नया सीखा।

भविष्य के ट्यूटोरियल्स में और अधिक दिलचस्प विषयों को लाने की कोशिश करेंगे। तब तक:

खुश रहने के लिए! ! ! !