J'ai implémenté un processus d'optimisation de Gauss-Newton qui consiste à calculer l'incrément en résolvant un système linéarisé Hx = b
. Le H
matrx est calculé par H = J.transpose() * W * J
et b
est calculé à partir de b = J.transpose() * (W * e)
où e
est le vecteur d'erreur. Jacobien est une matrice n-by-6 où n est en milliers et reste inchangé à travers les itérations et W
est une matrice de poids diagonale n-by-n qui changera à travers les itérations (certains éléments diagonaux seront mis à zéro). Cependant j'ai rencontré un problème de vitesse. Lorsque je n'ajoute pas la matrice de poids W
, à savoir H = J.transpose()*J
et b = J.transpose()*e
, mon processus Gauss-Newton peut fonctionner très rapidement en 0.02 sec pour 30 itérations. Cependant quand j'ajoute la matrice W
qui est définie en dehors de la boucle d'itération, elle devient si lente (0.3 ~ 0.7 sec pour 30 itérations) et je ne comprends pas si c'est mon problème de codage ou cela prend normalement beaucoup de temps.Multiplication de matrice très lente en Eigen
Tout ici sont des matrices et des vecteurs propres.
J'ai défini ma matrice W
en utilisant la fonction .asDiagonal()
dans la bibliothèque Eigen à partir d'un vecteur de variances inverses. alors juste utilisé dans le calcul pour H
ad b
. Ensuite, il devient très lent. Je voudrais avoir quelques indices sur les raisons potentielles de ce ralentissement énorme.
EDIT:
Il n'y a que deux matrices. Jacobian est définitivement dense. La matrice de poids est générée à partir d'un vecteur par la fonction vec.asDiagonal()
qui provient de la bibliothèque dense, donc je suppose qu'elle est également dense.
Le code est vraiment simple et la seule différence qui cause le changement d'heure est l'addition de la matrice de poids. Voici un extrait de code:
for (int iter=0; iter<max_iter; ++iter) {
// obtain error vector
error = ...
// calculate H and b - the fast one
Eigen::MatrixXf H = J.transpose() * J;
Eigen::VectorXf b = J.transpose() * error;
// calculate H and b - the slow one
Eigen::MatrixXf H = J.transpose() * weight_ * J;
Eigen::VectorXf b = J.transpose() * (weight_ * error);
// obtain delta and update state
del = H.ldlt().solve(b);
T <- T(del) // this is pseudo code, meaning update T with del
}
Il est en fonction dans une classe, et de la matrice de poids maintenant à des fins de débogage est défini comme une variable de classe qui peut être accessible par la fonction et est définie avant que la fonction est appelée .
'T <- T (del)' ?? – erip
@erip utilise del pour mettre à jour T – CathIAS
Vous avez déterminé (comparé) que le calcul de 'U' et' b' sont les goulets d'étranglement et non 'solve'? –