J'essaie de prendre la décomposition de la Groleky du produit d'une matrice avec sa transposition, en utilisant le type Eigen et C ++ 11 "Auto". Le problème vient lorsque j'essaie de faire J'utilise Xcode 6.1, Eigen 3.2.2. L'erreur de type que je reçois est ici . P> Cet exemple minimal montre le problème sur ma machine. Modifiez le type de C code> à partir de
auto code> à
matrixxd code> pour le voir fonctionner. P>
#include <iostream>
#include <Eigen/Eigen>
using namespace std;
using namespace Eigen;
int main(int argc, const char * argv[]) {
MatrixXd a = MatrixXd::Random(100, 3);
MatrixXd b = MatrixXd::Random(3, 100);
auto c = a * b;
auto cTc = c.transpose() * c;
auto chol = cTc.llt();
return 0;
}
4 Réponses :
Le problème est que la première multiplication renvoie un Edit: Je ne suis pas un expert sur le produit Eigen ou les caractéristiques de performance de faire le casting. Je viens de surmonter la réponse du message d'erreur et confirmée à partir de la documentation en ligne. Le profilage est toujours votre meilleur choix pour vérifier les performances de différentes parties de votre code. P> Eigen :: GeneralProduit code> au lieu d'un
matrixxd code> et
auto code> ramasse le type de retour. Vous pouvez implicirement créer un
matrixxd code> à partir d'un
Eigen :: GeneralProduit code> Ainsi, lorsque vous déclarez explicitement le type qu'il fonctionne correctement. Voir P >
Y a-t-il un coup de performance pour le casting à matrixxd code>? De toute évidence, dans cet exemple contraint, ce sera minime, mais dans la vie réelle? Que diriez-vous que la solution est ici - L'utilisation de productréturntype pour cela semblerait aller un peu fou lorsque vous effectuez le
c.tranpose () * C code> étape.
Je ne suis pas un expert à Eigen code>, mais les bibliothèques telles que ceci renvoient souvent des objets proxy des opérations, puis utilisent la conversion implicite ou les constructeurs pour forcer le travail réel. (Les modèles d'expression sont un exemple extrême de cela.) Cela évite de copier inutile de la matrice complète des données dans de nombreuses situations. Malheureusement,
auto code> est assez heureux de simplement créer un objet du type de proxy, qui normalement, les utilisateurs de la bibliothèque ne déclareraient jamais expliquer explicitement. Depuis que vous devez finalement avoir les chiffres calculés, il n'y a pas de performance frappé par SE de casting à un
matrixxd code>. (Scott Meyers, dans "Efficace moderne C ++", donne l'exemple associé d'utiliser
auto code> avec
vecteur
opérateur [] (Taille_t i) < / code> retourne un proxy.) p>
Ne pas utiliser Déduction de type auto Eigen en général P>
et a été conseillé par l'un des créateurs d'Eigen (GAEL) de ne pas utiliser Le casting d'une expression à un type spécifique tel que auto code> avec expressions d'Eigen. J'ai heurté des problèmes encore plus "dramatiques" avec cela avant, voir P>
auto code> avec expressions d'Eigen. p>
matrixxd code> devrait être extrêmement rapide, sauf si vous voulez une évaluation paresseuse (puisque lorsque le résultat est évalué). p>
Je pense que cela est légèrement différent du vôtre. Vous retournez un objet de ID code> à son tour référencé par
AutoFeResult code> - alors l'objet à partir de
ID code> disparaît et
AutoSult code > Références Quelque chose qui ne quitte pas.
c.transpose () code> références
c code>, qui existe toujours donc mon
auto CTC code> ne devrait pas faire référence à quelque chose qui n'existe pas - semblable à la façon dont GGAEL offre une solution à utiliser
auto = id = id (foo, 4) code>. Je voulais tester si Eigen peut remarquer correctement que
C.Transpose () * C = B.Transpose () *Transpose () * A * B code> qui simplifie le calcul, donc idéalement ce serait gardé comme une expression.
Oui, vous êtes correct, cependant, si je n'ai pas l'explication, je n'aurais absolument aucune idée de la raison pour laquelle le code s'est comporté anormalement. Et puisque Eigen a de nombreux types (fondamentalement, chaque expression est un type différent), plus le référencement indirect, auto code> rend les choses compliquées car vous n'êtes pas vraiment conscient de ce qui se passe sous la hotte et comment sont ces expressions évaluées.
Permettez-moi de résumer ce qui se passe et pourquoi c'est faux. Tout d'abord, instanecons les mots-clés code> code> avec les types qu'ils prennent: Notez que Eigen est une bibliothèque de modèles d'expression. Ici, équivalent à: p> xxx pré> puis le produit La dernière ligne: p> GeneralProduct code> est un type de résumé représentant le produit. Aucun calcul n'est effectué. Par conséquent, si vous copiez
CTC code> sur un
matrixxd code> comme: p>
a * b code> sera effectué deux fois! Donc, dans tout cas, il est très préférable d'évaluer
a * b code> dans un environnement temporaire explicite et identique pour
c ^ t * C code>: p>
auto c = a * b;
MatrixXd cTc = c.transpose() * c;
Merci - c'est vraiment génial d'entendre un développeur de la bibliothèque! Ma raison pour cela était de voir si Eigen pourrait optimiser correctement M0.Transpose () * M1.Transpose () * M2 * M3 Code> Quand ils ont des formes utiles - alors je voulais tout garder tout dans l'espace d'expression jusqu'à la dernière minute. Est-ce due à la manière dont les modèles fonctionnent que je ne peux pas prendre une décomposition de la Groleky d'un produit général, n'est-ce que personne n'a été suffisamment soignée pour l'ajouter à Eigen ou y a-t-il une raison pour laquelle il est stupide?