C++ 中的多线程不适用于 pybind11 到 Python

mutltithreading in C++ does not work with pybind11 to Python

我很难通过 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')

基本上计算器接受一个文件路径,然后 return 一个二维数组。我将此数据传回 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>());
}

然而 运行 只是崩溃。

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

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