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 就与此无关。
我很难通过 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 就与此无关。