【问题标题】:mutltithreading in C++ does not work with pybind11 to PythonC++ 中的多线程不适用于 pybind11 到 Python
【发布时间】:2021-12-29 18:52:03
【问题描述】:

我很难通过 python 的 pybind11 插件系统来利用 C++ 的多线程功能。我知道臭名昭著的 GIL 问题并尝试发布它但无济于事。以下是我的 C++ 代码:

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>

#include "Calculator.h" // where run_calculator is

namespace py = pybind11;

// wrap c++ function with Numpy array IO
int wrapper(const std::string& input_file, py::array_t<double>& in_results) {
    if (in_results.ndim() != 2)
        throw std::runtime_error("Results should be a 2-D Numpy array");

    auto buf = in_results.request();
    double* ptr = (double*)buf.ptr;

    size_t N = in_results.shape()[0];
    size_t M = in_results.shape()[1];

    std::vector<std::vector<double> > results;

    pybind11::gil_scoped_release release;
    run_calculator(input_file, results);
    pybind11::gil_scoped_acquire acquire;

    size_t pos = 0;
    for (size_t i = 0; i < results.size(); i++) {
        const std::vector<double>& line_data = results[i];
        for (size_t j = 0; j < line_data.size(); j++) {
            ptr[pos] = line_data[j];
            pos++;
        }
    }
}

PYBIND11_MODULE(calculator, m) {
    // optional module docstring
    m.doc() = "pybind11 calculator plugin";

    m.def("run_calculator", &wrapper, "Run the calculator");
}

然后在python端:

results= np.zeros((N, M))
start = datetime.datetime.now()
run_calculator(input_file, results)
end = datetime.datetime.now()
elapsed = end - start
print(f'the calculation takes {elapsed.total_seconds()} seconds')

基本上,计算器接受一个文件路径,然后返回一个二维数组。我将这些数据传回给 python。在计算器中,我放置了多线程。

然而,即使有了这个 pybind11::gil_scoped_release 版本,运行时间也没有减少。如果我在C++端运行使用main函数调用run_calculator,多线程的影响是非常明显的。

我也尝试过以这种方式将模块声明为pybind11,而不是使用gil_scoped_release

PYBIND11_MODULE(calculator, m) {
    // optional module docstring
    m.doc() = "pybind11 calculator plugin";

    m.def("run_calculator", &wrapper, py::call_guard<py::gil_scoped_release>());
}

但是运行只是崩溃了。

谁能给我指出正确的方向?

【问题讨论】:

  • 你怎么知道?这是一个单一的操作。线程如何在这里为您提供帮助?当然,run_calculator 的运行不会受到 Python 的影响。您的 GIL 版本唯一要做的就是允许其他 Python 线程同时运行。还有什么在运行?
  • 多线程位于 run_calculator 中。 input_file 有数百行数据,计算器会启动多线程并行处理这些行。我可以看到,如果只运行 C++ 部分,多线程确实会成比例地减少计算器的运行时间,但是使用 pybind11 并使用 python 驱动,实际上并没有减少计算器的运行时间。
  • 如果您在run_calculator 中使用多线程,GIL 根本不会影响这一点。 GIL 阻止多个 python 线程一起运行,但它不控制你的 C++ 代码的作用。
  • 你是对的。我现在确实看到了 C++ 中的多线程。

标签: python c++ multithreading pybind11 gil


【解决方案1】:

这是一个误报。多线程在 C++ 端工作。只要线程不在 python 端,GIL 就与此无关。

【讨论】:

    猜你喜欢
    • 2021-03-28
    • 2016-05-29
    • 1970-01-01
    • 2021-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-22
    相关资源
    最近更新 更多