2011-11-04 16 views
8

मैं boost.python का उपयोग कर lib अजगर में सी ++ कोड का एक टुकड़ा रैप करने के लिए कोशिश कर रहा हूँ, फिर भी, मुझे पता चला है कि कई उदाहरण एक ही समय में नहीं चल सकता:boost.python समानांतरता का समर्थन नहीं कर रहा है?

कोड (C++):

class Foo{ 
public: 
    Foo(){} 
    void run(){ 
     int seconds = 2; 
     clock_t endwait; 
     endwait = clock() + seconds * CLOCKS_PER_SEC ; 
     while (clock() < endwait) {} 
    } 

}; 

BOOST_PYTHON_MODULE(run_test) 
{ 
    using namespace boost::python; 

    class_<Foo>("test", init<>()) 
     .def("run", &Foo::run) 
     ; 

} 

जो CMake (CMake) का उपयोग कर संकलन है:

add_library(run_test SHARED run_test.cpp) 
target_link_libraries(run_test boost_python python2.7) 

और निम्नलिखित कोड (अजगर) के साथ परीक्षण किया:

class Dos(threading.Thread): 
    def run(self): 
     printl('performing DoS attack') 

     proc = test() 
     proc.run() 

for i in range(5): 
    t = Dos() 
    t.start() 

आउटपुट इंगित करता है कि कोड बहुत अजीब तरीके से समानांतर है। प्रत्येक धागा केवल 2 सेकंड लेना चाहिए और 4 धागे मेरी quadcore मशीन पर एक साथ चलना चाहिए:

[2011-11-04 13:57:01] performing DoS attack 
[2011-11-04 13:57:01] performing DoS attack 
[2011-11-04 13:57:05] performing DoS attack 
[2011-11-04 13:57:05] performing DoS attack 
[2011-11-04 13:57:09] performing DoS attack 

आपकी मदद के लिए धन्यवाद!

+9

, यह निश्चित रूप से एक वैध आवेदन की तरह दिखता है ...;) – larsmoa

+0

यदि आपने संकेत दिया कि कौन सा कोड पायथन था और सी ++ था तो यह पढ़ना आसान होगा। मैंने इसे समझ लिया, लेकिन मुझे एक पल लगा। –

उत्तर

16

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

Boost.Python के फायदों में से एक यह है कि आप जीआईएल जारी कर सकते हैं, सी ++ सामान कर सकते हैं, और फिर जब आप कर लेंगे तो इसे वापस ले लें। हालांकि यह भी एक जिम्मेदारी है। पाइथन आमतौर पर अन्य अंतराल को चलाने का मौका देने के लिए नियमित अंतराल पर जीआईएल जारी करता है। यदि आप सी ++ में हैं, तो यह आपका काम है। यदि आप जीआईएल धारण करते समय 2 घंटे के लिए क्रंच नंबर जाते हैं, तो आप पूरे दुभाषिया को जमा कर देंगे।

यह एक छोटे से रिवर्स आरए II के साथ ठीक करने के लिए आसान हो सकता है:

class releaseGIL{ 
public: 
    inline releaseGIL(){ 
     save_state = PyEval_SaveThread(); 
    } 

    inline ~releaseGIL(){ 
     PyEval_RestoreThread(save_state); 
    } 
private: 
    PyThreadState *save_state; 
}; 

अब तुम इतनी तरह अपने कोड बदल सकते हैं:

class Foo{ 
public: 
    Foo(){} 
    void run(){ 
     { 
      releaseGIL unlock = releaseGIL(); 
      int seconds = 2; 
      clock_t endwait; 
      endwait = clock() + seconds * CLOCKS_PER_SEC ; 
      while (clock() < endwait) {} 
     } 
    } 
}; 

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

दूसरी तरफ जाना भी संभव है। वर्तमान में जीआईएल धारण करने वाला एक थ्रेड इसे प्राप्त नहीं कर सकता है, और पाइथन में कॉल कर सकता है। यह एक धागा हो सकता है जो पहले जीआईएल जारी किया गया था, या एक जो सी ++ में शुरू हुआ था और कभी भी जीआईएल नहीं था। इसके लिए आरएआईआई कक्षा यहां है:

class AcquireGIL 
{ 
public: 
    inline AcquireGIL(){ 
     state = PyGILState_Ensure(); 
    } 

    inline ~AcquireGIL(){ 
     PyGILState_Release(state); 
    } 
private: 
    PyGILState_STATE state; 
}; 

उपयोग छात्र के लिए एक अभ्यास के रूप में छोड़ दिया गया है।

अतिरिक्त नोट (मैं हमेशा भूल जाते हैं यह उल्लेख करना):

आप C++ अपने मॉड्यूल परिभाषा इस कोड से प्रारंभ करना होगा में जीआईएल साथ खिलवाड़ किया जा रहा रहे हैं, तो: ठीक है

BOOST_PYTHON_MODULE(ModuleName) 
{ 
    PyEval_InitThreads(); 

    ... 
} 
+0

बहुत बहुत धन्यवाद! यह समस्या हल हो गई! – guinny

+0

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

+0

@ फ़ायरेंट: मेरे कोड को ठीक करने के लिए धन्यवाद। –

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