पायथन में धागे कैसे काम करते हैं, और सामान्य पायथन-थ्रेडिंग विशिष्ट नुकसान क्या हैं?


85

मैं अपने सिर को चारों ओर लपेटने की कोशिश कर रहा हूं कि पायथन में धागे कैसे काम करते हैं, और वे कैसे काम करते हैं, इसके बारे में अच्छी जानकारी प्राप्त करना कठिन है। मुझे बस एक लिंक या कुछ याद आ रही है, लेकिन ऐसा लगता है कि आधिकारिक दस्तावेज विषय पर बहुत अच्छी तरह से नहीं है, और मैं एक अच्छा लेखन नहीं पा सका हूं।

मैं जो बता सकता हूं, उससे केवल एक ही धागा एक बार में चल सकता है, और सक्रिय धागा हर 10 निर्देशों पर स्विच करता है?

जहां एक अच्छी व्याख्या है, या क्या आप एक प्रदान कर सकते हैं? पायथन के साथ थ्रेड्स का उपयोग करते समय सामान्य समस्याओं के बारे में पता होना भी बहुत अच्छा होगा।

जवाबों:


50

हां, ग्लोबल इंटरप्रेटर लॉक (GIL) की वजह से एक बार में केवल एक धागा ही चल सकता है। यहाँ इस बारे में कुछ अंतर्दृष्टि के साथ कुछ लिंक दिए गए हैं:

अंतिम कड़ी से एक दिलचस्प उद्धरण:

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

यदि आप मल्टी कोर का उपयोग करना चाहते हैं, तो वास्तविक समानांतरकरण करने के लिए pyprocessing एक प्रक्रिया आधारित API को परिभाषित करता है। पीईपी भी कुछ रोचक मानक भी शामिल है।


1
वास्तव में smoothspan बोली पर एक टिप्पणी: निश्चित रूप से पायथन प्रभावी रूप से आपको एक कोर तक सीमित करता है, भले ही मशीन में कई हों? मल्टीकोर से लाभ हो सकता है क्योंकि अगले धागे को एक संदर्भ स्विच के बिना जाने के लिए तैयार किया जा सकता है, लेकिन आपके पायथन थ्रेड्स एक समय में> 1 कोर का उपयोग कभी नहीं कर सकते हैं।
जेम्स ब्रैडी

2
सही, अजगर के धागे व्यावहारिक रूप से एक कोर तक सीमित हैं, UNLESS एक C मॉड्यूल GIL के साथ अच्छी तरह से इंटरैक्ट करता है, और यह स्वयं का मूल धागा चलाता है।
अराफांगियन

वास्तव में, कई कोर धागे को कम कुशल बनाते हैं क्योंकि जाँच के साथ बहुत अधिक मंथन होता है कि क्या प्रत्येक धागा GIL तक पहुँच सकता है। यहां तक ​​कि नई GIL की भी समझ है, प्रदर्शन अभी भी खराब है ... dabeaz.com/python/NewGIL.pdf
बेसिक

2
कृपया ध्यान दें कि GIL के विचार सभी व्याख्याकारों पर लागू नहीं होते हैं। जहां तक ​​मुझे GIL के बिना आयरनपाइथन और जाइथन फ़ंक्शन दोनों के बारे में पता है, उनके कोड को मल्टी-प्रोसेसर हार्डवेयर का अधिक प्रभावी उपयोग करने की अनुमति देता है। जैसा कि ऐराफैंगियन ने उल्लेख किया है, सीपीथॉन दुभाषिया भी ठीक से बहु-थ्रेड चल सकता है यदि कोड जिसे पायथन डेटा आइटम तक पहुंच की आवश्यकता नहीं है, तो लॉक को रिलीज़ करता है, फिर लौटने से पहले इसे फिर से प्राप्त करता है।
होल्डनवेब

पायथन में धागे के बीच एक संदर्भ स्विच का क्या कारण है? क्या यह टाइमर इंटरप्ट पर आधारित है? ब्लॉकिंग, या एक विशिष्ट उपज कॉल?
CMCDragonkai

36

पायथन में एक आसान भाषा है जिसे थ्रेड करना आसान है, लेकिन इसमें कैवियट हैं। ग्लोबल इंटरप्रेटर लॉक के बारे में सबसे बड़ी बात जो आपको जानना चाहिए। यह दुभाषिया तक पहुँचने के लिए केवल एक धागे की अनुमति देता है। इसका मतलब दो चीजें हैं: 1) आप शायद ही कभी अजगर और 2 में एक लॉक स्टेटमेंट का उपयोग करके खुद को पाते हैं) यदि आप मल्टी-प्रोसेसर सिस्टम का लाभ लेना चाहते हैं, तो आपको अलग-अलग प्रक्रियाओं का उपयोग करना होगा। EDIT: मुझे यह भी बताना चाहिए कि यदि आप GIL के आसपास भी जाना चाहते हैं तो आप कुछ कोड C / C ++ में डाल सकते हैं।

इस प्रकार, आपको फिर से विचार करने की आवश्यकता है कि आप थ्रेड्स का उपयोग क्यों करना चाहते हैं। यदि आप दोहरे कोर आर्किटेक्चर का लाभ उठाने के लिए अपने ऐप को समानांतर करना चाहते हैं, तो आपको अपने ऐप को कई प्रक्रियाओं में तोड़ने पर विचार करने की आवश्यकता है।

यदि आप जवाबदेही में सुधार करना चाहते हैं, तो आपको थ्रेड्स का उपयोग करके CONSIDER करना चाहिए। हालांकि अन्य विकल्प हैं, अर्थात् माइक्रोथ्रेडिंग । कुछ ऐसे ढांचे भी हैं जिन पर आपको गौर करना चाहिए:


@ जेएस - फिक्स्ड। वह सूची वैसे भी पुरानी थी।
जेसन बेकर

यह सिर्फ मेरे लिए गलत लगता है कि आपको मल्टी-कोर सिस्टम का लाभ उठाने के लिए कई प्रक्रियाओं की आवश्यकता होती है - सभी ओवरहेड के साथ। हमें 32 तार्किक कोर के साथ कुछ सर्वर मिले हैं - इसलिए मुझे कुशलता से उपयोग करने के लिए 32 प्रक्रियाओं की आवश्यकता है? पागलपन
बेसिक

@ बासिक - एक प्रक्रिया शुरू करने में ओवरहेड बनाम एक धागा शुरू करना इन दिनों न्यूनतम है। मुझे लगता है कि आप समस्याओं को देखना शुरू कर सकते हैं यदि हम प्रति सेकंड हजारों प्रश्नों के बारे में बात कर रहे हैं, लेकिन फिर मैं पहली बार ऐसी व्यस्त सेवा के लिए अजगर की पसंद पर सवाल उठाऊंगा।
जेसन बेकर

20

नीचे एक बुनियादी सूत्रण नमूना है। यह 20 धागे फैलाएगा; प्रत्येक थ्रेड अपने थ्रेड नंबर को आउटपुट करेगा। इसे चलाएं और उस क्रम का निरीक्षण करें जिसमें वे प्रिंट करते हैं।

import threading
class Foo (threading.Thread):
    def __init__(self,x):
        self.__x = x
        threading.Thread.__init__(self)
    def run (self):
          print str(self.__x)

for x in xrange(20):
    Foo(x).start()

जैसा कि आपने पायथन थ्रेड पर संकेत दिया है, समय-स्लाइसिंग के माध्यम से कार्यान्वित किया जाता है। इस तरह से उन्हें "समानांतर" प्रभाव मिलता है।

मेरे उदाहरण में मेरा फू वर्ग धागे को बढ़ाता है, मैं तब runविधि को लागू करता हूं , जो कि वह कोड है जिसे आप एक धागे में चलाना चाहते हैं। थ्रेड को आप start()थ्रेड ऑब्जेक्ट पर कॉल करना शुरू करने के लिए , जो स्वचालित रूप से runविधि को आमंत्रित करेगा ...

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


10

अजगर में धागे का उपयोग करें यदि व्यक्तिगत कार्यकर्ता I / O बाध्य संचालन कर रहे हैं। यदि आप एक मशीन पर कई कोर में बड़े पैमाने पर करने की कोशिश कर रहे हैं तो या तो अजगर के लिए एक अच्छा आईपीसी ढांचा ढूंढें या एक अलग भाषा चुनें।


4

नोट: जहाँ भी मेरा उल्लेख है, threadमेरा मतलब है कि विशेष रूप से अजगर में धागे स्पष्ट रूप से कहा गया है।

यदि आप C/C++पृष्ठभूमि से आ रहे हैं तो थ्रेड्स अजगर में थोड़ा अलग तरीके से काम करते हैं । अजगर में, केवल एक धागा दिए गए समय पर चालू स्थिति में हो सकता है। इसका मतलब है कि अजगर में धागे वास्तव में कई प्रसंस्करण कोर की शक्ति का लाभ नहीं उठा सकते हैं क्योंकि डिजाइन के लिए धागे के लिए कई कोर पर समानांतर रूप से चलाना संभव नहीं है।

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

Why does python use GIL?

एक साथ दुभाषिया राज्य तक पहुँचने और दुभाषिया राज्य को दूषित करने से कई धागों को रोकने के लिए।

विचार यह है कि जब भी किसी थ्रेड को निष्पादित किया जा रहा है (भले ही यह मुख्य धागा हो) , एक GIL का अधिग्रहण किया जाता है और समय के कुछ पूर्वनिर्धारित अंतराल के बाद GIL को वर्तमान थ्रेड द्वारा जारी किया जाता है और कुछ अन्य थ्रेड (यदि कोई हो) द्वारा पुनः प्राप्त किया जाता है।

Why not simply remove GIL?

ऐसा नहीं है कि जीआईएल को हटाना असंभव है, ऐसा सिर्फ इस तरह से करना है कि हम अंत तक पहुंचने के क्रम में इंटरप्रेटर के अंदर म्यूटेंट लॉक लगाते हैं, जिससे एक भी थ्रेडेड एप्लिकेशन कम परफॉर्म करता है।

इसलिए जीआईएल को हटाने की लागत का भुगतान एक एकल थ्रेडेड अनुप्रयोग के कम प्रदर्शन द्वारा किया जाता है, जो कभी वांछित नहीं होता है।

So when does thread switching occurs in python?

जब GIL जारी किया जाता है तब थ्रेड स्विच होता है। GIL का विमोचन कब किया जाता है? विचार करने के लिए दो परिदृश्य हैं।

यदि कोई थ्रेड CPU बाउंड ऑपरेशंस (Ex इमेज प्रोसेसिंग) कर रहा है।

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

थ्रेड स्विच करने के लिए मीट्रिक के रूप में निर्देश गणना का उपयोग करने के बजाय नए संस्करणों में, एक कॉन्फ़िगर करने योग्य समय अंतराल का उपयोग किया जाता है। डिफ़ॉल्ट स्विच अंतराल 5 मिलीसेकेंड है। आप वर्तमान स्विच अंतराल का उपयोग करके प्राप्त कर सकते हैं sys.getswitchinterval()। यह प्रयोग करके बदला जा सकता हैsys.setswitchinterval()

यदि कोई थ्रेड कुछ IO बाउंड ऑपरेशन कर रहा है (Ex फाइल सिस्टम एक्सेस या
नेटवर्क IO)

जब भी थ्रेड IO ऑपरेशन के पूरा होने की प्रतीक्षा कर रहा है, तब GIL जारी है।

Which thread to switch to next?

दुभाषिया का अपना शेड्यूलर नहीं है। जो थ्रेड अंतराल के अंत में अनुसूचित हो जाता है वह ऑपरेटिंग सिस्टम का निर्णय है। ।


3

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

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


2

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

मैं प्रोसेसर पर कई माता-पिता को सुझाव देने और एक ही कोर (एस) पर नौकरियों की तरह रखने की कोशिश करने के लिए इतनी दूर जाऊंगा।

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