代码之家  ›  专栏  ›  技术社区  ›  ilciavo

如何将eigen::ref与pybind11一起使用?

  •  1
  • ilciavo  · 技术社区  · 6 年前

    我使用PyBin来包装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);
    }
    

    如何避免创建 data 同样地 wrap2 , wrap3 或相当于 std::swap ?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Lack    6 年前

    修改数据失败:

    void wrap2(Eigen::MatrixXd& data){
    

    是的,这不会修改原始的numpy数组,因为pybind必须首先 复制 它变成一个临时的特征矩阵来调用 wrap2 . 来自 pybind Eigen docs :

    上述的一个主要限制是,每个数据转换都隐式地包含一个副本,这可能是昂贵的(对于大型矩阵)和 不允许更改其(矩阵)参数的绑定函数 . pybind11允许您使用eigens eigen::ref类来解决这个问题…

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

    但这一个未能编译:

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

    解决方案是定义一个接受 Eigen::参考 :

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

    另一个选择是 manipulate 函数模板。参见Eigen的文档 Writing Functions Taking Eigen Types as Parameters .