De ce que j'ai lu sur Eigen (ici), il semble qu' operator=()
agit comme une "barrière" de toutes sortes pour les paresseux de l'évaluation-par exemple, il provoque Propres à arrêter de retour de l'expression des modèles et de la performance de l' (optimisé) le calcul, le stockage du résultat dans la partie gauche de l' =
.
Cela semble signifier que le "style de codage" a un impact sur les performances -- c'est à dire en utilisant les variables nommées pour stocker le résultat de calculs intermédiaires pourrait avoir un effet négatif sur la performance de l'origine de certaines parties du calcul pour être évalué "trop tôt".
Pour tenter de vérifier mon intuition, j'ai écrit un exemple et a été surpris par les résultats (code complet ici):
using ArrayXf = Eigen::Array <float, Eigen::Dynamic, Eigen::Dynamic>;
using ArrayXcf = Eigen::Array <std::complex<float>, Eigen::Dynamic, Eigen::Dynamic>;
float test1( const MatrixXcf & mat )
{
ArrayXcf arr = mat.array();
ArrayXcf conj = arr.conjugate();
ArrayXcf magc = arr * conj;
ArrayXf mag = magc.real();
return mag.sum();
}
float test2( const MatrixXcf & mat )
{
return ( mat.array() * mat.array().conjugate() ).real().sum();
}
float test3( const MatrixXcf & mat )
{
ArrayXcf magc = ( mat.array() * mat.array().conjugate() );
ArrayXf mag = magc.real();
return mag.sum();
}
Le ci-dessus donne 3 différentes manières de calculer le coefficient de sage somme de grandeurs dans une valeur complexe de la matrice.
-
test1
de tri de chaque partie du calcul "une étape à la fois." -
test2
le calcul en une seule expression. -
test3
prend un "mélange" approche-avec une certaine quantité de variables intermédiaires.
J'ai attendu que, depuis test2
packs de la totalité de calcul en une seule expression, Eigen serait en mesure de prendre avantage de ce mondial et d'optimiser l'ensemble de calcul, offrant les meilleures performances.
Cependant, les résultats sont surprenants (les chiffres indiqués sont en total microsecondes à travers 1000 exécutions de chaque test):
test1_us: 154994
test2_us: 365231
test3_us: 36613
(Cela a été compilé avec g++ -O3 -- voir l'essentiel pour plus de détails.)
La version que j'ai prévu pour être le plus rapide (test2
) était en fait plus lent. En outre, la version que je m'attendais à être plus lent (test1
) était en fait dans le milieu.
Donc, mes questions sont les suivantes:
- Pourquoi est -
test3
effectuer beaucoup mieux que les autres? - Est-il une technique que l'on peut utiliser (à court de plonger dans le code assembleur) pour obtenir une certaine visibilité de la façon dont Eigen est effectivement mise en œuvre de vos calculs?
- Est-il un ensemble de lignes directrices à suivre pour trouver un bon compromis entre les performances et la lisibilité (utilisation de variables intermédiaires) dans votre Propre code?
En plus de calculs complexes, tout en un seul expression pourrait nuire à la lisibilité, donc je suis intéressé à trouver la bonne façon d'écrire le code qui est à la fois lisible et performant.