如何在pybind11中使用Eigen :: Ref?

时间:2018-10-25 00:49:57

标签: python c++ eigen3 pybind11

我正在使用pybind包装C ++代码。

给出以下函数,该函数最初是库的一部分,不应修改:

void manipulate(Eigen::MatrixXd& data) {
    data = data*2;
}

使用pybind,我可以将其包装为:

#include <pybind11/pybind11.h>
#include <pybind11/eigen.h>
#include <Eigen/LU>
namespace py = pybind11;

void wrap1(Eigen::Ref<Eigen::MatrixXd> data){
    Eigen::MatrixXd mData(data);
    manipulate(mData);
    data = mData;
}

PYBIND11_PLUGIN(cod) {
    pybind11::module m("cod", "auto-compiled c++ extension");
    m.def("wrap1", &wrap1);
    return m.ptr();
}

但这会创建不必要的副本mData

这无法修改数据:

void wrap2(Eigen::MatrixXd& data){
    manipulate(data);
}

这失败了,无法编译:

void wrap3(Eigen::Ref<Eigen::MatrixXd> data){
    manipulate(data);
}

如何避免像datawrap2或等效的wrap3一样创建std::swap的副本?

1 个答案:

答案 0 :(得分:1)

  

这无法修改数据:

void wrap2(Eigen::MatrixXd& data){

是的,这不会修改原始的numpy数组,因为pybind必须首先将其复制到临时的本征矩阵中才能调用wrap2。来自https://outlook.live.com/mail/inbox

  

上述内容的一个主要限制是,每个数据转换都隐式地涉及一个副本,这可能既昂贵(对于大型矩阵),又不允许绑定函数更改其(矩阵)参数。 Pybind11允许您使用Eigen的Eigen :: Ref类来解决此问题。

因此,我们必须使用Eigen::Ref

  

这失败了,无法编译:

void wrap3(Eigen::Ref<Eigen::MatrixXd> data){
    manipulate(data);
}

解决方案是定义一个接受Eigen::Ref的函数:

void manipulate(Eigen::Ref<Eigen::MatrixXd> data) {
    data = data*2;
}

另一个选择是使manipulate成为功能模板。请参阅pybind Eigen docs上的Eigen文档。