0

必要な複雑な計算を行うために、メンバー変数として Eigen 式テンプレートを格納するライブラリを作成しています。ただし、MatrixXd などで直接変換しない限り、これらの式テンプレートを保存または返すことができないようです。これにより、すべてのステップが一時的に保存され、設計全体の効率が損なわれます。

問題の原因となる短い例を次に示します。ホルダーは固有行列を保持するだけで、Summer は 2 つのホルダーを取得し、get() を呼び出すと、それらが保持する 2 つの行列の合計を出力します。次のテストは、合計式テンプレートが行列に評価されると失敗します (segfault または std::bad_alloc)。

インクルードファイル

#ifndef PB_SIMPLE_H
#define PB_SIMPLE_H

#include <Eigen/Dense>

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

   private:
    result_type in_;

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

template <class HoldLeft, class HoldRight>
class Summer {
   public:
    typedef const typename Eigen::CwiseBinaryOp<
        Eigen::internal::scalar_sum_op<double>,
        const typename HoldLeft::result_type,
        const typename HoldRight::result_type> result_type;
    // typedef Eigen::MatrixXd result_type;
   private:
    HoldLeft left_;
    HoldRight right_;

   public:
    Summer(const HoldLeft& left, const HoldRight& right)
        : left_(left), right_(right) {}

    result_type get() const { return left_.get() + right_.get(); }
};

typedef Holder<Eigen::MatrixXd> MatrixHolder;
typedef Summer<MatrixHolder, MatrixHolder> MatrixSummer;

#endif /* PB_SIMPLE_H */

簡単なテスト

#include "PbSimple.h"

#include <Eigen/Dense>

int main(int, char * []) {
  const unsigned int szx=10,szy=3;
  Eigen::MatrixXd x(Eigen::MatrixXd::Constant(szx,szy,1));
  MatrixHolder vx(x);
  Eigen::MatrixXd y(Eigen::MatrixXd::Constant(szx,szy,2));
  MatrixHolder vy(y);
  MatrixSummer vsum(vx,vy);
  auto expr = vsum.get();
  MatrixHolder vz(expr); //force evaluation of sum into new matrix, fails here
  return 0;
}
  • インクルード ファイルでは、代わりにコメント アウトされた typedef を使用すると、正常に動作します。
  • 問題はぶら下がっている参照によるものだと思われますが、それを証明することはできません。
4

1 に答える 1