2013-03-24 15 views
0

我得到了非常奇怪的行爲,我的python擴展與boost.python庫構建。即,在一段代碼:奇怪的時間python擴展execusion或建設boost.python與--threading = single

import my_ext 

j = 0 
while j<5: 
    print j 
    my_ext.do_something(j) 
    j = j + 1 

我沒有看到被打印從j個,而擴展碼(my_ext.do_something(j))是做不同Ĵ一些工作(可以說打印j個文件)。此外,它僅打印j = 0和j = 1的2個文件,然後整個腳本完成而沒有錯誤或其他通知。

所有這一切使我認爲代碼執行有點平行(多線程),但沒有適當處理這種parallelizm。我想這可能與我建立的boost.python庫默認使用--threading = multi選項有關。但是,嘗試使用--threading = single選項進行重建不會產生任何效果,並且仍然構建爲多線程庫。這篇文章http://mail.python.org/pipermail/cplusplus-sig/2010-October/015771.html報告了類似的構建過程問題,但它沒有得到答覆。

所以我的問題是如何建立boost庫和boost.python特別是單線程。或者,該問題可能與boost.python庫的單/多線程之外的其他內容有關。

附加信息:我使用的是cygwin,boost_1.50.0,python2.6,我的操作系統是Win 7,帶有多核CPU和nvidia vram(後者的硬件可能會支持多線程執行我的擴展而不讓我知道)。

回答

1

Boost.Python往往是Boost構建系統中的一個特例,因爲它與Python版本以及爲其構建Python的配置相結合。例如,如果Python是在沒有調試的情況下構建的,那麼Boost.Python將在沒有調試的情況下構建,即使明確告知Boost構建調試變體。我相信線程屬性也是如此,因爲它將通過包括Python.h間接包含pyconfig.h

Python默認在單線程中運行程序,無論Python是否使用線程支持構建。 Boost.Python不會改變這種行爲。作爲一般的經驗法則,當需要併發時,線程僅僅成爲Boost.Python的一個因素。例如,如果my_ext.do_something()要將大文件讀入內存,那麼執行讀操作可能是最佳的,而不需要保存lock on the interpreter

考慮從擴展的簡化實現開始,然後擴展它。例如,當我建立my_ext爲:

#include <iostream> 
#include <boost/python.hpp> 

void do_something(unsigned int j) 
{ 
    std::cout << "do_something(): " << j << std::endl; 
} 

BOOST_PYTHON_MODULE(my_ext) 
{ 
    namespace python = boost::python; 
    python::def("do_something", &do_something); 
} 

我的測試腳本:

import my_ext 

for j in xrange(5): 
    print j 
    my_ext.do_something(j) 

生產:

0 
do_something(): 0 
1 
do_something(): 1 
2 
do_something(): 2 
3 
do_something(): 3 
4 
do_something(): 4

另一種方法是建立Python和Boost.Python的調試版本,然後用調試器遍歷程序。有關調試版本的更多信息,請參閱here

+0

謝謝你,twsansbury,解釋。在我的情況下,實際的do_something功能相當複雜,並且導致了一些問題,所以一旦我解決了這些問題,整個組合就開始正常工作。但是,即使在正確執行do_something函數的情況下,也可能預期多線程支持可能會干擾並導致其他問題。但是,如果我正確理解你,在大多數情況下,這應該不是一個問題,除非python被顯式配置爲使用多個線程運行擴展。 – user938720 2013-03-25 23:58:22

+1

@ user938720:是的。即使Python是使用線程支持構建的,並且已經使用Python創建了多個線程,但它的併發性有限。基本上,在調用Python代碼時,解釋器可以執行合作良率,從而導致活動線程進入休眠狀態,等待線程進入活動狀態。當調用C擴展代碼時,如果擴展需要支持併發,則擴展必須顯式產生(釋放解釋器鎖),然後在返回到Python時重新獲取鎖。 – 2013-03-26 00:09:40