Ich möchte Boost.Proto verwenden, um eine eingebettete domänenspezifische Sprache in eine Reihe von Matrixoperationen umzuwandeln, die mit der Eigenbibliothek implementiert werden. Da Effizienz wichtig ist, möchte ich, dass proto Eigenexpressionsvorlagen generiert und eine vorzeitige Auswertung vermeidet.Konstruieren von Eigenexpressionsvorlagen mit Boost.Proto
Ich habe eine einfache Grammatik implementiert, die Matrixmultiplikationsausdrücke erzeugen kann. Der folgende Code kompiliert ohne Warnungen (auf g ++ 4.8.0 und Intel C++ 2013.3, mit Boost 1.54.0 und Eigen 3.1.3) und funktioniert so lange, wie mein Ausdruck nur eine einzige Multiplikation hat. Sobald ich der Kette weitere Multiplikationen hinzufüge, stürzt es ab. Valgrind sagt mir, dass dies daran liegt, dass eines der Expression-Template-Properties von Eigen: GeneralProduct vor der Auswertung zerstört wird.
Ich verstehe nicht, warum das passiert, oder was ich tun kann, um es zu verhindern. Alle Hilfe wird geschätzt!
#include <iostream>
#include <boost/fusion/container.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/void.hpp>
#include <boost/proto/proto.hpp>
#include <boost/ref.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility.hpp>
#include <Eigen/Dense>
namespace fusion = boost::fusion;
namespace mpl = boost::mpl;
namespace proto = boost::proto;
typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> matrix;
// Placeholders
const proto::terminal<mpl::int_<0> >::type I1 = {{}};
const proto::terminal<mpl::int_<1> >::type I2 = {{}};
const proto::terminal<mpl::int_<2> >::type I3 = {{}};
// Grammar
template<class Rule, class Callable = proto::callable>
struct External :
proto::when<Rule, proto::external_transform> {};
struct matmul_transform : proto::callable {
template<class Sig> struct result;
template<class This, class MatrixExpr1, class MatrixExpr2>
struct result<This(MatrixExpr1, MatrixExpr2)> {
typedef typename Eigen::ProductReturnType<
typename boost::remove_const<typename boost::remove_reference<MatrixExpr1>::type>::type,
typename boost::remove_const<typename boost::remove_reference<MatrixExpr2>::type>::type>::Type
type;
};
template<class MatrixExpr1, class MatrixExpr2>
typename result<matmul_transform(MatrixExpr1, MatrixExpr2)>::type
operator()(const MatrixExpr1 &a, const MatrixExpr2 &b) const {
return a * b;
}
};
struct MatmulGrammar;
struct InputPlaceholder : proto::terminal<proto::_> {};
struct MatrixMultiplication :
proto::multiplies<MatmulGrammar, MatmulGrammar> {};
struct MatmulGrammar : proto::or_<
External<InputPlaceholder>,
External<MatrixMultiplication> > {};
struct matmul_transforms : proto::external_transforms<
proto::when<MatrixMultiplication, matmul_transform(MatmulGrammar(proto::_left), MatmulGrammar(proto::_right))>,
proto::when<InputPlaceholder, proto::functional::at(proto::_data, proto::_value)> > {};
int main() {
matrix mat1(2,2), mat2(2,2), mat3(2,2), result(2,2);
mat1 << 1, 2, 3, 4;
mat2 << 5, 6, 7, 8;
mat3 << 1, 3, 6, 9;
MatmulGrammar mmg;
// THIS WORKS:
result = mmg(I1 * I2,
mpl::void_(),
(proto::data = fusion::make_vector(boost::cref(mat1), boost::cref(mat2), boost::cref(mat3)),
proto::transforms = matmul_transforms()));
std::cout << result << std::endl;
// THIS CRASHES:
result = mmg(I1 * I2 * I3,
mpl::void_(),
(proto::data = fusion::make_vector(boost::cref(mat1), boost::cref(mat2), boost::cref(mat3)),
proto::transforms = matmul_transforms()));
std::cout << result << std::endl;
return 0;
}
Es war ein Gespräch in diesem Jahr C++ Jetzt über Eigen mit proto verwenden. Wenn ich mich richtig erinnere, haben sie explizit über dieses Problem gesprochen und erklärt, wie sie es gelöst haben. Sie finden die Folien [hier] (https://github.com/boostcon/cppnow_presentations_2013/blob/master/fri/proto-eigen-fem.pdf?raw=true), das Video des Vortrags [hier] (http: // www : //www.youtube.com/watch? v = pDTQlwXkjvU) und der Quellcode [hier] (https://github.com/barche/eigen-proto) wenn Sie interessiert sind.Leider fehlt in den letzten Minuten der Ton, aber bis dahin läuft alles gut. – llonesmiz