【问题标题】:is boost::python not a thread-safe while running using OpenMP?使用 OpenMP 运行时 boost::python 不是线程安全的吗?
【发布时间】:2021-11-08 17:46:11
【问题描述】:

我尝试了一些关于在 OpenMP 中实现 boost::python 的简单示例。这是一个:

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

namespace p = boost::python;

int main() {
    Py_Initialize();
    p::object glob = p::import("glob");
    // glob.glob list more than 7000 files
    p::object paths = glob.attr("glob")("C:\\path\\to\\the\\dir\\location");

    #pragma omp parallel for default(shared) schedule(dynamic)
    for (int i = 0; i < p::len(paths); i++) {
        std::cout << p::extract<const char *>(p::str(paths[i])) << std::endl; 
    }
    std::cout << "finished: " << p::len(paths) << std::endl;
    return 0;
}

如果不使用 OpenMP,该代码可以正常工作。但是,如果使用它,我会收到 139 的错误。我也尝试过使用 Python API (PyObject *),但仍然遇到同样的问题。我已经指出问题出在我们导入 Python 模块时。

因此,我们是否有可能在 boost::python 或 Python C API 上使用并行编程,尤其是当我们在 C++ 上使用 Python 模块时?

【问题讨论】:

    标签: python c++ boost


    【解决方案1】:

    我在此链接上找到了解决方案:multithreading-with-python-and-c-api。答案是,由于 GIL,我们无法真正使用 Python 创建多线程程序。

    我将上面的代码修改成这样(我根据previous link的解决方案使用了参考here):

    #include <omp.h>
    #include <iostream>
    #include <boost/python.hpp>
    
    namespace p = boost::python;
    
    // -- I CITE THIS CODE SNIPPET BASED ON THE REFERENCE BELOW --
    // link: https://gist.github.com/sterin/e8090d0451ab781a4e22
    // initialize and clean up python
    struct initialize
    {
        initialize()
        {
            Py_InitializeEx(1);
            PyEval_InitThreads();
        }
    
        ~initialize()
        {
            Py_Finalize();
        }
    };
    
    // acquire GIL
    class ensure_gil_state
    {
    public:
        ensure_gil_state()
        {
            _state = PyGILState_Ensure();
        }
    
        ~ensure_gil_state()
        {
            PyGILState_Release(_state);
        }
    
    private:
        PyGILState_STATE _state;
    };
    
    // allow other threads to run
    class enable_threads
    {
    public:
        enable_threads()
        {
            _state = PyEval_SaveThread();
        }
    
        ~enable_threads()
        {
            PyEval_RestoreThread(_state);
        }
    
    private:
        PyThreadState* _state;
    };
    // --------------------------------------------------
    
    int main() {
        initialize init;
        p::object glob = p::import("glob");
        // we have more than 7000 files
        p::object paths = glob.attr("glob")("C:\\path\\to\\the\\dir\\location");
    
        {
        enable_threads enable_threads_scope;
        #pragma omp parallel for
        for (int i = 0; i < p::len(paths); i++) {
            std::string pathi;
            {
                ensure_gil_state gil_scope;
                pathi = p::extract<const char *>(p::str(paths[i]));
                std::cout << i << " " << pathi << std::endl;
                std::cout << " -> out of scope" << std::endl;
            }
        }
        }
        std::cout << "finished: " << p::len(paths) << std::endl;
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-05
      • 2023-03-29
      • 1970-01-01
      • 2013-09-24
      • 2011-12-30
      • 2011-09-16
      • 1970-01-01
      • 2010-12-15
      相关资源
      最近更新 更多