【问题标题】:strange timing of the python extension execusion or building boost.python with --threading=singlepython 扩展执行的奇怪时机或使用 --threading=single 构建 boost.python
【发布时间】:2013-03-24 00:51:31
【问题描述】:

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

所有这一切让我觉得代码是并行执行的(多线程),但没有正确处理这种并行化。我想这可能与我构建的 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(后两种硬件都可能支持我的扩展程序的多线程执行而不让我知道)。

【问题讨论】:

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


    【解决方案1】:

    Boost.Python 往往是 Boost 构建系统中的一个特例,因为它与 Python 构建的 Python 版本和配置相耦合。例如,如果 Python 是在没有调试的情况下构建的,那么 Boost.Python 将在没有调试的情况下构建,即使 Boost 被明确告知构建一个调试变体。我相信 threading 属性也是如此,因为它会通过包含 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
    做某事():0
    1
    做某事():1
    2
    做某事():2
    3
    做某事():3
    4
    do_something(): 4

    另一种方法是构建 Python 和 Boost.Python 的调试版本,然后使用调试器逐步执行程序。有关调试版本的更多信息,请访问here

    【讨论】:

    • 感谢 twsansbury 的解释。在我的情况下,实际的 do_something 函数非常复杂,它会导致一些问题,所以一旦我解决了这些问题,整个组合就开始正常工作。然而,即使在正确执行 do_something 函数的情况下,也可以预期多线程支持可能会干扰并导致其他问题。但是,如果我理解正确的话,在大多数情况下,这应该不是问题,除非 python 被明确配置为使用多线程运行扩展。
    • @user938720:是的。即使 Python 是使用线程支持构建的,并且在 Python 中创建了多个线程,它的并发性也是有限的。基本上,在调用 Python 代码时,解释器可以进行协作让步,使活动线程休眠,而待处理线程进入活动状态。在调用 C 扩展代码时,如果扩展想要支持并发,则必须显式让出(释放解释器锁),然后在返回 Python 时重新获取锁。
    猜你喜欢
    • 1970-01-01
    • 2013-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多