क्या पायथन मल्टीथ्रेडिंग का समर्थन करता है? क्या यह निष्पादन के समय को गति दे सकता है?


95

मैं इस बारे में थोड़ा उलझन में हूं कि पाइथन में मल्टीथ्रेडिंग काम करता है या नहीं।

मुझे पता है कि इस बारे में बहुत सारे सवाल हैं और मैंने उनमें से कई को पढ़ा है, लेकिन मैं अभी भी भ्रमित हूं। मैं अपने स्वयं के अनुभव से जानता हूं और दूसरों को स्टैकऑवरफ्लो पर अपने स्वयं के उत्तर और उदाहरण पोस्ट करते हुए देखा है कि वास्तव में पाइथन में मल्टीथ्रेडिंग संभव है। तो ऐसा क्यों है कि हर कोई कहता है कि अजगर जीआईएल द्वारा बंद है और एक समय में केवल एक धागा ही चल सकता है? यह स्पष्ट रूप से काम करता है। या कुछ भेद है जो मुझे यहाँ नहीं मिल रहा है?

कई पोस्टर / उत्तरदाता यह भी उल्लेख करते हैं कि थ्रेडिंग सीमित है क्योंकि यह कई कोर का उपयोग नहीं करता है। लेकिन मैं कहूंगा कि वे अभी भी उपयोगी हैं क्योंकि वे एक साथ काम करते हैं और इस तरह संयुक्त कार्यभार को तेजी से पूरा करते हैं। मेरा मतलब है कि एक पायथन थ्रेड मॉड्यूल भी क्यों होगा?

अपडेट करें:

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

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

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

मुझे मल्टीप्रोसेसिंग मॉड्यूल के बारे में भी पता है, लेकिन अभी मेरा मुख्य हित छोटे से मध्यम कार्य भार (10-30 सेकंड) के लिए है और इसलिए मुझे लगता है कि मल्टीथ्रेडिंग अधिक उपयुक्त होगा क्योंकि उपप्रोसेस आरंभ करने के लिए धीमा हो सकता है।


4
यह एक बहुत भरा हुआ सवाल है। मुझे लगता है कि उत्तर में निहित है कि आप क्या करना चाहते हैं। अधिकांश परिस्थितियों में GIL एक से अधिक थ्रेड को एक साथ चलने से रोकता है। हालांकि, कुछ मामले हैं जहां जीआईएल जारी किया गया है (उदाहरण के लिए एक फ़ाइल से पढ़ना) ताकि समानांतर में किया जा सके। यह भी ध्यान दें कि GIL Cpython का कार्यान्वयन विवरण है (सबसे आम कार्यान्वयन)। अजगर (जेथॉन, पाइपी, आदि) का कोई अन्य कार्यान्वयन GIL (AFAIK) नहीं है
mgilson

2
@mgilson PyPy में एक GIL है।

2
@delnan - आप सही प्रतीत होते हैं। धन्यवाद।
21

1
"उपप्रकारों को आरंभ करने में धीमा हो सकता है" - आप निष्पादित करने के लिए तैयार कार्यों का एक पूल बना सकते हैं। ओवरहेड को काम शुरू करने के लिए आवश्यक डेटा को क्रमबद्ध / deserialize करने में लगने वाले समय की मात्रा तक सीमित किया जा सकता है।
ब्रायन कैन

1
@KarimBahgat, मेरा वास्तव में यही मतलब है।
ब्रायन कैन

जवाबों:


132

GIL थ्रेडिंग को नहीं रोकता है। सभी जीआईएल सुनिश्चित करते हैं कि केवल एक धागा एक समय में पायथन कोड को निष्पादित कर रहा है; नियंत्रण अभी भी थ्रेड्स के बीच स्विच करता है।

फिर GIL क्या रोकता है, समानांतर में थ्रेड चलाने के लिए एक से अधिक CPU कोर या अलग CPU का उपयोग कर रहा है।

यह केवल पायथन कोड पर लागू होता है। C एक्सटेंशन GIL को C कोड के कई थ्रेड्स और एक Python थ्रेड को कई कोर में चलाने की अनुमति देने के लिए जारी और कर सकते हैं। यह कर्नेल द्वारा नियंत्रित I / O तक फैली हुई है, जैसे select()सॉकेट के लिए कॉल पढ़ता है और लिखता है, जिससे पायथन संभाल नेटवर्क घटनाओं को एक बहु-थ्रेडेड मल्टी-कोर सेटअप में कुशलतापूर्वक सक्षम बनाता है।

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

ध्यान दें कि GIL केवल CPython कार्यान्वयन के लिए लागू है; Jython और IronPython एक अलग थ्रेडिंग कार्यान्वयन (क्रमशः देशी जावा VM और .NET सामान्य रनटाइम थ्रेड्स) का उपयोग करते हैं।

सीधे अपने अपडेट को संबोधित करने के लिए: कोई भी कार्य जो समानांतर पायथन कोड का उपयोग करके समानांतर निष्पादन से गति को बढ़ावा देने की कोशिश करता है, एक स्पीड-अप नहीं देखेगा क्योंकि थ्रेडेड पायथन कोड एक समय में निष्पादित होने वाले एक थ्रेड पर लॉक होता है। यदि आप C एक्सटेंशन और I / O में मिलाते हैं, हालांकि (जैसे PIL या संख्यात्मक ऑपरेशन) और कोई भी C कोड एक सक्रिय पायथन धागे के साथ समानांतर में चल सकता है ।

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


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

4
नहीं, मुझे नहीं लगता कि ऐसा उत्तर बहुत मददगार होगा; ईमानदार रहना। आप कभी भी एक विस्तृत सूची नहीं बना सकते हैं, लेकिन नियम का अंगूठा यह है कि कोई भी I / O (फ़ाइल पढ़ना और लिखना, नेटवर्क सॉकेट, पाइप) C में संभाला जाता है, और बहुत से C पुस्तकालय उनके लिए GIL भी जारी करते हैं संचालन, लेकिन यह पुस्तकालयों पर निर्भर करता है कि वह आपके लिए यह दस्तावेज करे।
मार्टिन पीटर्स

1
मेरा बुरा, अब तक आपके अपडेट किए गए उत्तर को नहीं देखा, जहां आपने थ्रेड के उपयोग के कुछ अच्छे उदाहरण दिए हैं। इनमें शामिल हैं (मुझे गलत करें तो Im गलत) नेटवर्क प्रोग्रामिंग (जैसे urllib.urlopen()?), पायथन GUI के भीतर से एक पायथन स्क्रिप्ट को कॉल करने के लिए, और थ्रेड के साथ कई PIL (जैसे Image.transform()) और numpy (जैसे numpy.array()) संचालन को कॉल करना । और आपने अपनी टिप्पणी में कुछ और उदाहरण दिए जैसे कि फ़ाइलों को पढ़ने के लिए कई थ्रेड्स का उपयोग करना (जैसे f.read()?)। मुझे पता है कि एक संपूर्ण सूची संभव नहीं है, बस आपको अपने अपडेट में दिए गए उदाहरणों के प्रकार चाहिए थे। किसी भी तरह से, आपके उत्तर को स्वीकार कर लिया :)
करीम बहगट

2
@KarimBahgat: हां, urllib.urlopen()नेटवर्क सॉकेट्स को लागू करेगा, सॉकेट I / O के लिए थ्रेड स्विच करने और कुछ और करने का एक शानदार अवसर है।
मार्टिन पीटर्स

4
हालाँकि यह सीधे तौर पर इस समस्या के लिए प्रासंगिक नहीं है, यह ध्यान देने योग्य है कि कभी-कभी थ्रेडिंग प्रदर्शन के बारे में बिल्कुल नहीं है; निष्पादन के कई स्वतंत्र सूत्र के रूप में अपने कोड को लिखना सरल हो सकता है। उदाहरण के लिए, आपके पास एक थ्रेड बैकग्राउंड म्यूजिक हो सकता है, एक यूआई की सर्विसिंग कर सकता है, और एक कॉउंटिंग को दूर किया जा सकता है, जो अंततः किया जाना है लेकिन किसी भी जल्दी में नहीं है। UI रनरूप के साथ अगले ऑडियो बफ़र को चलाने के लिए अनुक्रम करने की कोशिश कर रहा है, या अंतःक्रिया के साथ हस्तक्षेप न करने के लिए अपने कम्प्यूटेशन को छोटे पर्याप्त टुकड़ों में तोड़ सकता है, थ्रेड्स का उपयोग करने की तुलना में बहुत कठिन हो सकता है।
ab Augert

4

हाँ। :)

आपके पास निम्न स्तर का थ्रेड मॉड्यूल और उच्च स्तर थ्रेडिंग मॉड्यूल है। लेकिन यह आप केवल मल्टीकोर मशीनों का उपयोग करना चाहते हैं, मल्टीप्रोसेसिंग मॉड्यूल जाने का रास्ता है।

डॉक्स से उद्धरण :

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


3

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

इसलिए मूल रूप से यदि आप गणना को गति देने के लिए कोड को मल्टी-थ्रेड करना चाहते हैं, तो यह गति नहीं देगा क्योंकि एक समय में केवल एक थ्रेड निष्पादित होता है, लेकिन यदि आप इसका उपयोग डेटाबेस के साथ बातचीत करने के लिए करते हैं, तो उदाहरण के लिए।

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