Как использовать Eigen :: Ref с 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);
}

Как я могу избежать создания копии data, а также wrap2, wrap3 или эквивалента std::swap?


person ilciavo    schedule 25.10.2018    source источник


Ответы (1)


Это не может изменить данные:

void wrap2(Eigen::MatrixXd& data){

Да, это не изменит исходный массив numpy, потому что pybind сначала должен скопировать его во временную матрицу Eigen для вызова wrap2. Из документов pybind Eigen:

Одним из основных ограничений вышеизложенного является то, что каждое преобразование данных неявно включает в себя копию, что может быть как дорогостоящим (для больших матриц), так и запрещает функции привязки, которые изменяют свои (матричные) аргументы. Pybind11 позволяет обойти это, используя класс Eigen :: Ref от Eigen ...

Следовательно, мы должны использовать Eigen::Ref.

И этот не может быть скомпилирован:

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

Решение состоит в том, чтобы определить функцию, которая принимает Eigen::Ref:

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

Другой вариант - сделать manipulate шаблон функции. См. Документацию Эйгена по Написанию функций, принимающих собственные типы в качестве параметров.

person Lack    schedule 28.10.2018
comment
Проблема в том, что manipulate является частью библиотеки, которую я не могу изменить. Спасибо за ответ - person ilciavo; 29.10.2018
comment
вы можете создать лямбда-функцию, которая обертывает манипулирование, чтобы принимать Eigen::Ref - person shelper; 23.09.2020