Как отслеживать собственные объекты с помощью метода execute ()?

Этот вопрос связан с приведение из Eigen :: CwiseBinaryOp к MatrixXd вызывает segfault .
Вероятно, оно будет иметь такое же простое решение, как и первое.

В этом минимальном примере я определяю Holder, которая содержит и собственную матрицу, и возвращает ее через get() функция-член. Так же, Decomp шаблон выражения для разложения LDLT этой матрицы, и Solve решает для AX = B, давая X.

#include <Eigen/Dense>
#include <Eigen/Cholesky>

template <class EigenType> class Holder {
public:
typedef EigenType result_type;

private:
result_type in_;

public:
Holder(const EigenType& in) : in_(in) {}
const result_type& get() const { return in_; }
};

template <class Hold> class Decomp {
public:
typedef typename Eigen::LDLT
<typename Eigen::MatrixBase<typename Hold::result_type>::PlainObject>
result_type;

private:
Hold mat_;

public:
Decomp(const Hold& mat) : mat_(mat) {}

result_type get() const { return mat_.get().ldlt(); }
};

template <class Derived, class OtherDerived> class Solve {
public:
typedef typename Eigen::internal::solve_retval
<typename Derived::result_type, typename OtherDerived::result_type>
result_type;

private:
Derived decomp_;
// typename Derived::result_type decomp_;
OtherDerived mat_;

public:
Solve(const Derived& decomp, const OtherDerived& mat)
: decomp_(decomp), mat_(mat) {}
//: decomp_(decomp.get()), mat_(mat) {}

result_type get() const { return decomp_.get().solve(mat_.get()); }
// result_type get() const { return decomp_.solve(mat_.get()); }
};

typedef Holder<Eigen::MatrixXd> MatrixHolder;
typedef Decomp<MatrixHolder> MatrixDecomp;
typedef Solve<MatrixDecomp, MatrixHolder> SimpleSolve;

Следующий тест не пройден X.get()

#include "Simple.h"#include <Eigen/Dense>
#include <iostream>

int main(int, char * []) {
MatrixHolder A(Eigen::MatrixXd::Identity(3, 3));
MatrixHolder B(Eigen::MatrixXd::Random(3, 2));
MatrixDecomp ldlt(A);
SimpleSolve X(ldlt, B);
std::cout << X.get() << std::endl;
return 0;
}

но если вы используете закомментированные строки в заголовочном файле, все работает нормально. К сожалению, это переносит оценку разложения в конструкцию решателя, которая не подходит для моего использования. Как правило, я хочу построить сложное выражение expr с участием этого Solveи позвоните expr.get() позже.

Как я могу решить эту проблему? Есть ли общее правило, которому нужно следовать, чтобы избежать дальнейших вопросов?

0

Решение

Чтобы избежать ненужных и дорогих копий, внутренние solve_retval структура хранит декомпозицию и правую часть по константным ссылкам. Тем не менее LDLT объект, созданный в Decomp::get функция удаляется в то же время, что функция возвращает, и, следовательно, solve_retval объект ссылается на мертвые объекты.

Один из возможных обходных путей, это добавить Decomp::result_type объект в Solveи инициализировать его в Solve::get, Кроме того, чтобы избежать нескольких глубоких копий, я предлагаю использовать константные ссылки для нескольких атрибутов следующим образом:

#include <Eigen/Dense>
#include <Eigen/Cholesky>

template <class EigenType> class Holder {
public:
typedef EigenType result_type;

private:
result_type in_;

public:
Holder(const EigenType& in) : in_(in) {}
const result_type& get() const { return in_; }
};

template <class Hold> class Decomp {
public:
typedef typename Eigen::LDLT
<typename Eigen::MatrixBase<typename Hold::result_type>::PlainObject>
result_type;

private:
const Hold& mat_;
mutable result_type result_;
mutable bool init_;

public:
Decomp(const Hold& mat) : mat_(mat), init_(false) {}

const result_type& get() const {
if(!init_) {
init_ = true;
result_.compute(mat_.get());
return result_;
}
}
};

template <class Derived, class OtherDerived> class Solve {
public:
typedef typename Eigen::internal::solve_retval
<typename Derived::result_type, typename OtherDerived::result_type>
result_type;

private:
const Derived& decomp_;
const OtherDerived& mat_;

public:
Solve(const Derived& decomp, const OtherDerived& mat)
: decomp_(decomp), mat_(mat) {}

result_type get() const {
return decomp_.get().solve(mat_.get());
}
};

Общее правило состоит в том, чтобы хранить тяжелые объекты по константной ссылке (чтобы избежать глубоких копий) и облегченные выражения по значению (чтобы уменьшить временные проблемы жизни).

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector