python扩展执行的奇怪时机或使用--threading = single构建boost.python

时间:2013-03-24 00:51:31

标签: python multithreading boost thread-safety boost-python

我对使用boost.python库构建的python扩展的行为非常奇怪。即,在一段代码中:

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个文件)。此外,它只打印2个文件,j = 0和j = 1,然后整个脚本完成没有错误或其他通知。

所有这些让我觉得代码是并行执行的(多线程),但没有正确处理这样的并行化。我想这可能与我建立的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,我的操作系统是带有多核CPU和nvidia vram的Win 7(后者的harware可能都支持多线程执行我的扩展而不让我知道)。

1 个答案:

答案 0 :(得分:1)

Boost.Python往往是Boost构建系统中的一个特例,因为它与已构建Python的Python版本和配置相关联。例如,如果Python是在没有调试的情况下构建的,那么Boost.Python将在没有调试的情况下构建,即使明确告知Boost构建调试变体。我相信线程属性也是如此,因为它会通过包含pyconfig.h来间接包含Python.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找到。