[英]pybind11 speeding up function calls
我有几个我使用pybind11在Python中构造的C ++函数对象,然后将这些对象从Python传递到另一个调用它们的C ++函数。 由于这些函数具有状态,因此它们不会针对无状态python函数进行pybind11优化,并且性能非常慢。
我可以通过一个丑陋的方法解决此问题,该方法将创建的C ++对象的指针返回给Python,然后将其传递回调用方C ++函数。 但是,我希望有一种更清洁,更可维护的方式来执行此操作。
这是一些基于以下代码进行复制的代码(import_call_execute嵌入Python进程并运行它): https ://pythonextensionpatterns.readthedocs.io/en/latest/debugging/debug_in_ide.html
下面的第一个python程序在我的机器上花费163毫秒,第二个仅花费0.5毫秒
#include <pybind11/pybind11.h>
#include <pybind11/functional.h>
#include <iostream>
#include <chrono>
#include "py_import_call_execute.hpp"
using namespace std;
using namespace std::chrono;
using namespace pybind11::literals;
namespace py = pybind11;
class TestFunc {
public:
TestFunc(int a): _a(a) {}
int operator()(int b) const {
return _a + b;
}
size_t get_ptr() {
return (size_t)this;
}
private:
int _a;
};
int test_dummy_function(const std::function<int(int)> &f) {
auto start = high_resolution_clock::now();
int sum = 0;
for (int i = 0; i < 100000; ++i) {
sum += f(i);
}
auto stop = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(stop - start);
cout << "sum: " << sum << " time: " << duration.count() / 1000.0 << " milliseconds" << endl;
return sum;
}
int test_dummy_function2(std::size_t ptr) {
auto start = high_resolution_clock::now();
TestFunc* f = reinterpret_cast<TestFunc*>(ptr);
int sum = 0;
for (int i = 0; i < 100000; ++i) {
sum += (*f)(i);
}
auto stop = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(stop - start);
cout << "sum: " << sum << " time: " << duration.count() / 1000.0 << " milliseconds" << endl;
return sum;
}
PYBIND11_MODULE(pybind_testing, m) {
py::class_<TestFunc>(m, "TestFunc")
.def(py::init<int>(), "a"_a)
.def("__call__", &TestFunc::operator(), "b"_a = 3)
.def("get_ptr", &TestFunc::get_ptr);
m.def("test_dummy_function", test_dummy_function);
m.def("test_dummy_function2", test_dummy_function2);
}
int main(int argc, const char *argv[]) {
argc = 4;
const char *argv2[] = {
"python",
"/Users/sal/Developer/coatbridge/testing/pybind11",
"test_pybind11",
"test_pybind11"};
return import_call_execute(argc, argv2);
}
Python功能1:
import pybind_testing as pt
def test_pybind11():
test_func = pt.TestFunc(2)
pt.test_dummy_function(test_func)
Python功能2:
import pybind_testing as pt
def test_pybind11():
test_func = pt.TestFunc(2)
pt.test_dummy_function2(test_func.get_ptr())
糟糕的性能与pybind11或Python无关。 这很慢,因为您正在使用std::function
,这与常规函数调用完全不同。
您可以通过以下方式替换main()
的代码来看到:
TestFunc test_func(2);
test_dummy_function(test_func);
test_dummy_function2(test_func.get_ptr());
要修复它,只需停止使用std::function
。 您可以通过引用或(智能?)指针直接传递TestFunc
对象。 应该没有必要将地址转换为size_t
并再次返回的技巧(尽管请注意,如果确实需要这样做,则正确的类型是uintptr_t
而不是size_t
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.