2012-05-16 13 views
16

मैं एक बहुप्रचारित सी अनुप्रयोग में पायथन दुभाषिया एम्बेड कर रहा हूं और मैं थोड़ी उलझन में हूं कि थ्रेड सुरक्षा सुनिश्चित करने के लिए मुझे किन एपीआई का उपयोग करना चाहिए।मल्टीथ्रेडेड सी अनुप्रयोग में पाइथन एम्बेड करना

जो मैंने एकत्र किया है, जब से मैं पाइथन एम्बेड करता हूं, यह किसी भी अन्य पायथन सी एपीआई कॉल को कॉल करने से पहले जीआईएल लॉक की देखभाल करने के लिए एम्बेडर पर निर्भर करता है। यह इन कार्यों के साथ किया जाता है:

gstate = PyGILState_Ensure(); 
// do some python api calls, run python scripts 
PyGILState_Release(gstate); 

लेकिन यह अकेला पर्याप्त प्रतीत नहीं होता है। मुझे अभी भी यादृच्छिक दुर्घटनाएं मिली हैं क्योंकि यह पाइथन एपीआई के लिए आपसी बहिष्करण प्रदान नहीं कर रही है।

कुछ और डॉक्स मैं यह भी कहा पढ़ने के बाद:

PyEval_InitThreads(); 

सही Py_IsInitialized() करने के लिए कॉल के बाद, लेकिन वह जहां भ्रामक हिस्सा आता है। डॉक्स राज्य इस समारोह है कि:

प्रारंभ और वैश्विक दुभाषिया ताला

यह पता चलता है कि जब इस समारोह रिटर्न, गिल माना जाता है बंद किया जा करने के लिए और किसी भी तरह को अनलॉक कर दिया जाना चाहिए प्राप्त करते हैं। लेकिन व्यवहार में यह आवश्यक प्रतीत नहीं होता है। इस लाइन के साथ मेरी बहुप्रचारित पूरी तरह से काम करती है और पारस्परिक बहिष्कार PyGILState_Ensure/Release कार्यों द्वारा बनाए रखा गया था।
जब मैंने PyEval_ReleaseLock()PyEval_ReleaseLock() के बाद PyEval_ReleaseLock() जोड़ने की कोशिश की तो ऐप PyImport_ExecCodeModule() पर बाद में कॉल में बहुत जल्दी लॉक हो गया।

तो मैं यहां क्या खो रहा हूं?

उत्तर

4

आखिर में मैंने इसे समझ लिया।

बाद
PyEval_InitThreads(); 

आप जबकि ठीक से मुख्य थ्रेड के लिए जीआईएल जारी

PyEval_SaveThread(); 

कॉल करने के लिए की जरूरत है।

+0

यह गलत और संभावित रूप से हानिकारक है: 'PyEval_SaveThread' हमेशा' PyEval_RestoreThread' के संयोजन के साथ होना चाहिए। जैसा कि [कहीं और समझाया गया है] (http://stackoverflow.com/a/15471525/1600898), आपको इसे प्रारंभ करने के बाद लॉक को रिलीज़ करने का प्रयास नहीं करना चाहिए; इसे अपने नियमित काम के हिस्से के रूप में रिलीज़ करने के लिए इसे पायथन पर छोड़ दें। – user4815162342

+0

मुझे नहीं लगता कि यह हानिकारक क्यों है यदि आप सभी कॉल को _Block_ _Allow_ ब्लॉक में पाइथन में डालते हैं। दूसरी तरफ, यदि आप 'PyEval_SaveThread();' नहीं कहते हैं, तो आपका मुख्य धागा अन्य धागे की पहुंच को पायथन तक अवरुद्ध कर देगा। दूसरे शब्दों में 'PyGILState_Ensure() 'deadlocks। – khkarens

+0

यह एकमात्र चीज है जो दोनों पायथन को एम्बेड करने और एक्सटेंशन मॉड्यूल में कॉल करने के लिए काम करती है। –

-1

एक बहु-थ्रेडेड सी ऐप एकाधिक थ्रेड से संवाद करने की कोशिश कर रहा है जिसमें एक ही सीपीथन उदाहरण के एकाधिक पायथन थ्रेड्स मेरे लिए जोखिम भरा लग रहा है।

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

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

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

+1

आपने वास्तव में प्रश्न का उत्तर नहीं दिया है। मुझे एक धागे पर काम कतार में दिलचस्पी नहीं है। – shoosh

5

मुझे बिल्कुल वही समस्या थी और अब का उपयोग करके के तुरंत बाद हल किया गया है, जैसा कि आप ऊपर बताते हैं।हालांकि, मेरी वास्तविक समस्या यह थी कि मैंने PyInitialise() के बाद उपयोग किया जो तब PyGILState_Ensure() को अलग-अलग, बाद के देशी धागे से बुलाए जाने के लिए अवरुद्ध करता था।

  1. वहाँ वैश्विक चर रहा है:

    static int gil_init = 0; 
    
  2. एक मुख्य थ्रेड से देशी सी एक्सटेंशन लोड और अजगर दुभाषिया शुरू:

    Py_Initialize() 
    
  3. सारांश में, यह अब मैं क्या कर रहा है
  4. कई अन्य धागे से मेरा ऐप समेकित रूप से पाइथन/सी एपीआई में बहुत सी कॉल करता है:

    if (!gil_init) { 
        gil_init = 1; 
        PyEval_InitThreads(); 
        PyEval_SaveThread(); 
    } 
    state = PyGILState_Ensure(); 
    // Call Python/C API functions...  
    PyGILState_Release(state); 
    
  5. मुख्य थ्रेड से अजगर दुभाषिया

    Py_Finalize() 
    

अन्य सभी समाधान मैं कोशिश की है या तो रोक यादृच्छिक अजगर sigfaults या गतिरोध/PyGILState_Ensure() का उपयोग कर अवरुद्ध का कारण बना।

पायथन दस्तावेज़ वास्तव में इस पर अधिक स्पष्ट होना चाहिए और कम से कम एम्बेडिंग और एक्सटेंशन उपयोग दोनों मामलों के लिए एक उदाहरण प्रदान करना चाहिए।

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