7
votes

Comment accélérer le produit matriciel de la bibliothèque d'Eigen?

J'étudie une multiplication simple de deux grandes matrices à l'aide de la bibliothèque Eigen. Cette multiplication semble être sensiblement plus lente que MATLAB et Python pour les mêmes matrices de taille.

Y a-t-il quelque chose à faire pour rendre l'opération Eigen plus rapidement?

Détails du problème

x: matrice aléatoire de 1000 x 50000

y: aléatoire 50000 x 300 matrice

Expériences de synchronisation (à ma fin de 2011 MacBook Pro)

Utilisation MATLAB: X * Y prend environ 1,3 sec

Utilisation de l'enthousiasme Python: numpy.dot (x, y) prend ~ 2,2 sec

Utiliser Eigen: x * y prend ~ 2,7 sec

Détails Eigen

Vous pouvez obtenir mon code eigen (comme fonction MEX): https://gist.github.com / Michaelchughes / 4742878

Cette fonction MEX se lit sous deux matrices de Matlab et renvoie leur produit.

Exécution de cette fonction MEX sans l'opération de produit matricielle (c'est-à-dire que tout simplement faire l'IO) produit des frais généraux négligeables, de sorte que l'IO entre la fonction et le matlab n'explique pas la grande différence de performance. C'est clairement l'opération réelle du produit matriciel.

Je compile avec g ++, avec ces drapeaux d'optimisation: "-O3 -DNDEBUG"

J'utilise les derniers fichiers d'en-tête Eigen stable (3.1.2).

Toute suggestion sur la manière d'améliorer la performance de l'Eigen? Quelqu'un peut-il reproduire l'écart que je vois?

mise à jour Le compilateur semble vraiment compiler. Le chronométrage d'origine Eigen a été effectué à l'aide de la version d'Apple Xcode de G ++: LLVM-G ++ - 4.2.

Quand j'utilise g ++ - 4.7 téléchargé via MacPorts (même CXXOPTIMFLAGS), je reçois 2,4 secondes au lieu de 2.7.

Toute autre suggestion de compiler mieux serait très appréciée.

Vous pouvez également obtenir un code RAW C ++ pour cette expérience: https://gist.github.com/michaelchughes / 4747789

./ Matporeigen 1000 50000 300

rapporte 2,4 secondes sous g ++ - 4.7


4 commentaires

Savez-vous quel algorithme il met en œuvre? On dirait qu'il peut simplement utiliser un algorithme de multiplication matricielle de merde. Une autre chose à essayer consiste à activer la vectorisation automatique: gcc.gnu.org/projects /tree-ssa/vectorisation.html (pas par défaut, je ne pense pas ... Eh bien, peut-être. Pas sûr). Si vous êtes sur une machine Intel, essayez d'utiliser Intel Compiler ... J'ai remarqué que cela surpasse toujours tout le monde en optimisation. Voir aussi ici eigen.tuxfamily.org/index.php?title=faq#vectorisation


@ STHANG: Eigen a été conçu pour une algèbre linéaire, donc je serais surpris si l'algorithme utilisé est aussi mauvais. Vectorisation des arbres est activée par défaut avec l'indicateur d'optimisation "-O3" que j'utilise selon votre lien, ce n'est donc pas le problème AFAIK. Je pourrais essayer Intel Compiler si aucune autre suggestion ne s'approche.


@Mikehuges, vous pouvez également essayer de tracer le taux de croissance car la taille de la matrice augmente et peut donner des indices quant à ce qui se passe. Cela devrait donner une indication de l'algorithme qu'il utilise. ou bien, creuser dans leur source ou leur documentation.


Bonjour, il m'a fallu environ 260 secondes pour exécuter le code C ++ sur ma machine, j'utilise VS2012 et Windows, mon processeur est Core I5-4570. Tout en testant la matrice multiplie, cela m'a également pris environ 1,3 seconde. Cela assez câblé.


3 Réponses :


12
votes

Tout d'abord, lors de la comparaison de performance, vous permet de désactiver Turbo-Boost (TB). Sur mon système, à l'aide de GCC 4.5 de Macport et sans Turbo-Boost, je reçois 3,5 ans, qui correspond à 8,4 gflops tandis que le pic théorique de mon noyau I7 2.3 est de 9,2 gflops, donc pas trop mal.

MATLAB est basé sur Intel MKL et constatez les performances rapportées, il utilise clairement une version multithreadée. Il est peu probable qu'une petite bibliothèque comme Eigen puisse battre Intel sur son propre processeur!

Numpy peut utiliser n'importe quelle bibliothèque BLAS, Atlas, MKL, Openblas, Eigen-Blas, etc. Je suppose que dans votre cas, il utilisait Atlas qui est rapide aussi.

Enfin, voici comment vous pouvez obtenir de meilleures performances : Activer le multi-threading dans Eigen en compilant avec -fopenmp. Par défaut, Eigen utilise pour le nombre de threads le nombre de thread par défaut défini par OpenMP. Malheureusement, ce nombre correspond au nombre de cœurs logiques et non à des cœurs physiques, alors assurez-vous que l'hyper-threading est désactivé ou définir la variable d'environnement OMP_NUM_THTHEADS au nombre physique de cœurs. Ici, je reçois des 1.25s (sans tb) et 0,95s avec la tuberculose.


4 commentaires

Bon appel à la multithreading: Matlab Multhreading semble expliquer la majeure partie de la différence. Lorsque j'utilise l'option de ligne de commande "-SingLecompThead", les horloges MATLAB à environ 2,4 secondes, identiques à Eigen.


Je ne peux penser à aucune raison de bonne raison pour que vous définissez omp_num_threads à autre chose que le nombre de noyaux logiques dans ce cas. Si vous le définissez au nombre de cœurs physiques avec HT activé, vous ferez simplement 50% de la CPU ...


Fondamentalement, HT permet de masquer les latences de mémoire et d'améliorer la pipeline d'instructions en exécutant deux threads sur le même noyau physique. Cependant, une routine de produits matricielle bien implémentée comme dans Eigen occupe déjà près de 100% des unités arithmétiques, la pipeline est déjà parfaite et les latences de mémoire sont déjà bien cachées. Dans ce contexte, ht ne peut détruire que la performance. Par exemple, les deux threads accéderont simultanément à la même ressource de cache L1 annulant ainsi l'avantage du cache L1.


Enfin, j'ai vérifié Eigen uniquement utilisé SSE et MKL a utilisé AVX. C'est un facteur de deux pertes. Depuis eux, Haswell est sorti avec FMA. Je ne sais pas si MKL soutient FMA, mais si cela fait, c'est un autre facteur de deux pertes (quatre total). Mon propre code GEMM que j'ai écrit est terminé deux fois plus vite que Eigen utilisant OpenMP et FMA.



2
votes

La raison pour laquelle MATLAB est plus rapide est parce qu'il utilise l'Intel MKL. Eigen peut l'utiliser aussi (voir ici ), mais vous devez bien sûr l'acheter .

Cela étant dit, il y a un certain nombre de raisons pour lesquelles vous pouvez être plus lent. Pour comparer Python VS Matlab VS Eigen, vous devez réellement coder trois versions équivalentes d'une opération dans les langues respectives. Notez également que Matlab Caches Resulces, vous auriez donc vraiment besoin de commencer par une nouvelle session MATLAB pour vous assurer que sa magie ne vous trompe pas.

aussi, MEX MEX de Matlab n'est pas inexistant . L'OP Il présente des versions plus récentes "Corrigez" le problème, mais je serais surpris si toutes les frais générales ont été complètement effacées.


2 commentaires

Pour mon cas particulier (en utilisant R2011b), la surcharge de l'appel MEX est pas la cause principale. Pour vérifier, j'ai écrit un version pure C ++ de ce test et a donné les mêmes timings que Ce que j'ai branché le mex à (~ 2,4 secondes). J'ai aussi couru mon Version MEX afin que ce soit seulement l'IO en commentant la ligne qui fait la ligne qui fait le produit matriciel. Ce bit Io seulement (tous les frais généraux) a couru dans ~ .001 sec.


De plus, les «résultats de la mise en cache» Matlab ne semblent pas non plus expliquer les choses non plus. J'ai couru de nombreux débats frais (à l'aide de l'interface de ligne de commande) et de toutes les horloge à environ 1,3 sec. C'est clairement la multithreading (voir le poste de Ggael ci-dessous).



2
votes

Eigen ne profite pas des instructions AVX introduites par Intel avec l'architecture de pont sableux. Cela explique probablement la majeure partie de la différence de performance entre Eigen et Matlab. J'ai trouvé une succursale qui ajoute la prise en charge de AVX à https://bitbucket.org/benoitteeiner/eigen mais comme Loin que je peux le dire, il n'a pas encore été fusionné dans le coffre de l'Eigen.


1 commentaires

Ouais et FMA ajoute un autre facteur de deux. Je ne sais pas si une bibliothèque soutient encore la FMA.