首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >pybind11加速函数调用

pybind11加速函数调用
EN

Stack Overflow用户
提问于 2018-10-21 06:54:47
回答 1查看 1.2K关注 0票数 0

我有几个使用pybind11在Python语言中构造的C++函数对象,然后将这些对象从Python语言传递给另一个调用它们的C++函数。因为这些函数是有状态的,所以它们没有经过无状态python函数的pybind11优化,性能非常慢。

我可以通过一个丑陋的技巧来解决这个问题,它将创建的C++对象的指针返回给Python,然后Python将指针传递回调用者的C++函数。然而,我希望有一种更干净,更可维护的方式来做这件事。

下面是一些基于https://pythonextensionpatterns.readthedocs.io/en/latest/debugging/debug_in_ide.html的复制代码(import_call_execute嵌入了Python进程并运行它):

下面的第一个python程序在我的机器上需要163毫秒,第二个程序只需要0.5毫秒

代码语言:javascript
复制
#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:

代码语言:javascript
复制
import pybind_testing as pt

def test_pybind11():
    test_func = pt.TestFunc(2)
    pt.test_dummy_function(test_func)

Python函数2:

代码语言:javascript
复制
import pybind_testing as pt

def test_pybind11():
    test_func = pt.TestFunc(2)
    pt.test_dummy_function2(test_func.get_ptr())
EN

回答 1

Stack Overflow用户

发布于 2018-10-21 09:23:46

性能不佳与pybind11或Python无关。它之所以很慢,是因为您使用的是std::function,它与常规函数调用完全不同。

您可以通过将main()中的代码替换为以下代码来查看:

代码语言:javascript
复制
TestFunc test_func(2);
test_dummy_function(test_func);
test_dummy_function2(test_func.get_ptr());

要修复它,只需停止使用std::function即可。您可以直接通过引用或(smart?)传递TestFunc对象。指针。应该不需要将其地址来回转换为size_t (尽管请注意,如果您确实需要这样做,正确的类型应该是uintptr_t而不是size_t)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52910755

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档