2009-03-16 11 views
18

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

उत्तर

7

पायथन के लिए सी/सी ++ एक्सटेंशन जीआईएल द्वारा बंधे नहीं हैं। हालांकि, आपको वास्तव में यह जानने की जरूरत है कि आप क्या कर रहे हैं। From http://docs.python.org/c-api/init.html:

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

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

+2

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

+0

मुझे लगता है कि ओपी संदिग्ध है। आप एक सी विस्तार में एक थ्रेड स्पिन कर सकते हैं जो जीआईएल द्वारा बाध्य नहीं है। –

16

हां, सी एक्सटेंशन (पायथन से बुलाए गए सी रूटीन) को कॉल अभी भी जीआईएल के अधीन है।

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

जानकारी के लिए, Py_BEGIN_ALLOW_THREADS और Py_END_ALLOW_THREADS मैक्रो पर एक नज़र डालें: http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock

9

यहाँ एक लंबा लेख मैं अजगर पत्रिका है कि सी विस्तार/जीआईएल/सूत्रण बात पर छू लेती है के लिए लिखा था है। यह 4000 शब्दों पर थोड़ा लंबा है, लेकिन इसे मदद करनी चाहिए।

http://jessenoller.com/2009/02/01/python-threads-and-the-global-interpreter-lock/

+1

यह एक बहुत अच्छा अवलोकन है। –

0

चेक बाहर Cython, यह अजगर के लिए, लेकिन "cdef", तेजी से numpy पहुँच कार्यों जैसे कुछ निर्माणों के साथ इसी तरह वाक्य रचना है, और एक बयान "nogil साथ" (जो करता है जो यह कहता है)।

0

यदि आप सी ++ में अपना एक्सटेंशन लिख रहे हैं, तो आप जीआईएल में हेरफेर करने वाले कोड को आसानी से और आसानी से लिखने के लिए आरएआईआई का उपयोग कर सकते हैं। मैं आरए II structlets की यह जोड़ी का उपयोग करें:

namespace py { 

    namespace gil { 

     struct release { 
      PyThreadState* state; 
      bool active; 

      release() 
       :state(PyEval_SaveThread()), active(true) 
       {} 

      ~release() { if (active) { restore(); } } 

      void restore() { 
       PyEval_RestoreThread(state); 
       active = false; 
      } 
     }; 

     struct ensure { 
      PyGILState_STATE* state; 
      bool active; 

      ensure() 
       :state(PyGILState_Ensure()), active(true) 
       {} 

      ~ensure() { if (active) { restore(); } } 

      void restore() { 
       PyGILState_Release(state); 
       active = false; 
      } 
     }; 

    } 

} 

... इजाजत दी जीआईएल दिए गए ब्लॉक (एक अर्थ ढंग से है कि किसी भी संदर्भ प्रबंधक Pythonista प्रशंसकों के लिए dimly परिचित लग सकता है) के लिए टॉगल किया जा करने के लिए:

PyObject* YourPythonExtensionFunction(PyObject* self, PyObject* args) { 

    Py_SomeCAPICall(…);  /// generally, if it starts with Py* it needs the GIL 
    Py_SomeOtherCall(…); /// ... there are exceptions, see the docs 

    { 
     py::gil::release nogil; 
     std::cout << "Faster and less block-y I/O" << std::endl 
        << "can run inside this block -" << std::endl 
        << "unimpeded by the GIL"; 
    } 

    Py_EvenMoreAPICallsForWhichTheGILMustBeInPlace(…); 

} 

... दरअसल, व्यक्तिगत रूप से मुझे पाइथन को विस्तारित करने में आसानी मिलती है, और नियंत्रण के स्तर में आंतरिक संरचनाओं और राज्य, एक हत्यारा सुविधा है।

+0

एनबी यदि आप इनमें से किसी भी एपीआई कॉल का उपयोग कर रहे हैं, तो आप पहले मैन्युअल जीआईएल नियंत्रण का प्रयास करने से पहले 'PyEval_InitThreads() '(जैसे आपके मॉड्यूल प्रारंभिक फ़ंक्शन में) प्रारंभिक कॉल करना चाहते हैं। – fish2000

संबंधित मुद्दे