gpt4 book ai didi

python - pybind11 加速函数调用

转载 作者:行者123 更新时间:2023-11-28 04:31:00 25 4
gpt4 key购买 nike

我有几个使用 pybind11 在 Python 中构建的 C++ 函数对象,然后将这些对象从 Python 传递给调用它们的另一个 C++ 函数。由于这些函数是有状态的,它们没有经过pybind11针对无状态python函数的优化,性能很慢。

我可以通过一个丑陋的 hack 来解决这个问题,该 hack 将创建的 C++ 对象的指针返回给 Python,然后 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).

关于python - pybind11 加速函数调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52910755/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com