必要な複雑な計算を行うために、メンバー変数として 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 を使用すると、正常に動作します。
- 問題はぶら下がっている参照によるものだと思われますが、それを証明することはできません。