खोज…


टिप्पणियों

GIL क्यों है?

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

लघु संस्करण: जीआईएल यह सुनिश्चित करता है कि आपके पास कितने भी प्रोसेसर और धागे हों, केवल अजगर इंटरप्रेटर का एक धागा एक समय में चलेगा।

इसके उपयोग में बहुत आसानी है, लेकिन साथ ही साथ इसके बहुत सारे नकारात्मक लाभ भी हैं।

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

जिन दुभाषियों के पास GIL है: CPython, PyPy, Cython (लेकिन आप nogil साथ GIL को निष्क्रिय कर सकते हैं)

जिन दुभाषियों के पास GIL नहीं है: Jython, IronPython

जीआईएल कैसे काम करता है: पर विवरण

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

जब सीपीआई एक I / O ऑपरेशन करता है, तो CPython स्वचालित रूप से GIL जारी करता है। इमेज प्रोसेसिंग लाइब्रेरी और संख्यात्मक संख्या क्रंचिंग ऑपरेशन्स जीआईएल को अपनी प्रोसेसिंग करने से पहले जारी करते हैं।

जीआईएल के लाभ

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

जीआईएल के परिणाम

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

संदर्भ:

https://wiki.python.org/moin/GlobalInterpreterLock - यह क्या करता है का त्वरित सारांश, सभी लाभों के बारे में ठीक जानकारी

http://programmers.stackexchange.com/questions/186889/why-was-python-written-with-the-gil - स्पष्ट रूप से लिखित सारांश

http://www.dabeaz.com/python/UnderstandingGIL.pdf - GIL कैसे काम करता है और यह कई कोर पर धीमा क्यों होता है

http://www.dabeaz.com/GIL/gilvis/index.html - डेटा का दृश्य दिखा रहा है कि कैसे GIL धागे को लॉक करता है

http://jeffknupp.com/blog/2012/03/31/pythons-hardest-problem/ - GIL समस्या के इतिहास को समझने में सरल

https://jeffknupp.com/blog/2013/06/30/pythons-hardest-problem-revisited/ - GIL की सीमाओं के आसपास काम करने के तरीकों पर विवरण

Multiprocessing.Pool

पाइथन में थ्रेड्स का उपयोग कैसे करें, यह पूछने पर सरल उत्तर है: "इसके बजाय प्रक्रियाओं का उपयोग न करें।" मल्टीप्रोसेसिंग मॉड्यूल आपको थ्रेड बनाने के लिए समान सिंटैक्स के साथ प्रक्रियाएं बनाने देता है, लेकिन मैं उनके सुविधाजनक पूल ऑब्जेक्ट का उपयोग करना पसंद करता हूं।

डेविड बेज़ले ने जीआईएल के खिलाफ थ्रेड्स के खतरों को दिखाने के लिए पहले कोड का उपयोग करके, हम इसे मल्टीप्रोसेसिंग का उपयोग करके फिर से लिखेंगे।

डेविड बेज़ले का कोड जिसने GIL को थ्रेडिंग की समस्याएं दिखाईं

from threading import Thread
import time
def countdown(n):
    while n > 0:
        n -= 1

COUNT = 10000000

t1 = Thread(target=countdown,args=(COUNT/2,))
t2 = Thread(target=countdown,args=(COUNT/2,))
start = time.time()
t1.start();t2.start()
t1.join();t2.join()
end = time.time()
print end-start
मल्टीप्रोसेसिंग का उपयोग करके फिर से लिखा गया।
import multiprocessing
import time
def countdown(n):
    while n > 0:
        n -= 1

COUNT = 10000000

start = time.time()
with multiprocessing.Pool as pool:
    pool.map(countdown, [COUNT/2, COUNT/2])

    pool.close()
    pool.join()

end = time.time()
print(end-start)

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

मैंने पाया है कि बयान के with भी, यदि आप पास नहीं हैं और पूल में शामिल नहीं होते हैं, तो प्रक्रियाएं मौजूद हैं। संसाधनों को साफ करने के लिए, मैं हमेशा अपने पूलों को बंद करता हूं और जुड़ता हूं।

साइथन नोगिल:

साइथॉन एक वैकल्पिक अजगर दुभाषिया है। यह GIL का उपयोग करता है, लेकिन आपको इसे अक्षम कर देता है। उनके प्रलेखन देखें

एक उदाहरण के रूप में, डेविड बेज़ले ने जीआईएल के खिलाफ थ्रेड्स के खतरों को दिखाने के लिए कोड का उपयोग करके, हम इसे nogil का उपयोग करके फिर से लिखेंगे:

डेविड बेज़ले का कोड जिसने GIL को थ्रेडिंग की समस्याएं दिखाईं

from threading import Thread
import time
def countdown(n):
    while n > 0:
        n -= 1

COUNT = 10000000

t1 = Thread(target=countdown,args=(COUNT/2,))
t2 = Thread(target=countdown,args=(COUNT/2,))
start = time.time()
t1.start();t2.start()
t1.join();t2.join()
end = time.time()
print end-start

Nogil (केवल CYTHON में काम करता है) का उपयोग करके फिर से लिखा गया है:

from threading import Thread
import time
def countdown(n):
    while n > 0:
        n -= 1

COUNT = 10000000

with nogil:
    t1 = Thread(target=countdown,args=(COUNT/2,))
    t2 = Thread(target=countdown,args=(COUNT/2,))
    start = time.time()
    t1.start();t2.start()
    t1.join();t2.join()
    
end = time.time()
print end-start

जब तक आप साइथन का उपयोग कर रहे हैं, यह इतना आसान है। ध्यान दें कि दस्तावेज़ कहता है कि आपको यह सुनिश्चित करना चाहिए कि किसी भी अजगर वस्तुओं को न बदलें:

बयान के शरीर में कोड को किसी भी तरह से पायथन ऑब्जेक्ट्स में हेरफेर नहीं करना चाहिए, और जीआईएल को फिर से प्राप्त किए बिना पायथन ऑब्जेक्ट्स को हेरफेर करने वाली किसी भी चीज़ को कॉल नहीं करना चाहिए। साइथन वर्तमान में यह जाँच नहीं करता है।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow