Donc ce code permet de faire une multiplication de matrices assez classique.
Le probleme c'est que si je commente la boucle
for(size_t k = 0; k < this->m_width; k+=8)
et que je decommente l'autre boucle, mon code s'execute environ 4 fois plus rapidement, avec l'option -O3
Quelqu'un aurait une idée??
J'utilise cette multiplication dans un strassen que j'ai parlleliser. Peut-etre que le les threads doivent attendre pour avoir acces aux registres mmx??
Attention tu as coupé la ligne 14 au lieu de la copier.
Il y a des conversions de type dans tes boucles (tmp est int, les SIMD sont float et les éléments des tableaux des T que tu n'a pas précisé). Sachant qu'une conversion float<=>int est plus couteuse qu'une multiplication, la plupart du CPU est dans les conversions et dans la fonction sum8() que je ne connais pas. Suivant le type T que tu utilises, il y auras des gains très différents. L'optimiseur a certainement mieux géré les conversions et cela ne m'étonne pas qu'il fasse mieux.
J'avoue, je ne connais pas __m256 et ce genre de types. Car tout ce qui est spécifique à certains processeurs, je préfère laisser le compilo l'optimiser.
As tu essayé de comparer ta version à un code sans __m256, pour voir si le compilo arrive à faire aussi bien, voir mieux ?
Car parfois, en forçant l'optimisation, on débranche des optimisations automatique qui sont bien plus performantes.
Après il faut connaître quelques règles : les instructions SIMD sont invoquées dans les for quand il n'y a pas de if dedans par exemple. Et c'est le cas dans ton code.
Il y a un (voire deux) problèmes d’inefficacités au niveau de la gestion de la mémoire dynamique avant d'aller chercher la réécriture avec une utilisation explicite de la vectorisation.
Si vraiment tu veux des perfs, je ne vois aucune raison de ne pas employer une bibliothèque dédiée (eigen/blaze/armadillo) et de plugger le noyau de calculs sur la MKL que l'on peut obtenir légalement et gratuitement aujourd'hui.
Maintenant, ma multiplication avec des int est 2 fois plus rapide que celle naive avec les optimisations.
Mais avec des float, elle est toujours environ 2 fois plus lente.
Merci de vos reponses
lmghs a écrit:
Il y a un (voire deux) problèmes d’inefficacités au niveau de la gestion de la mémoire dynamique avant d'aller chercher la réécriture avec une utilisation explicite de la vectorisation.
Si vraiment tu veux des perfs, je ne vois aucune raison de ne pas employer une bibliothèque dédiée (eigen/blaze/armadillo) et de plugger le noyau de calculs sur la MKL que l'on peut obtenir légalement et gratuitement aujourd'hui.
Salut, tu peux preciser svp que je puisse corriger ca.
Tu as une allocation+libération en plein milieu d'un boucle.
Et tu vas générer une nouvelle matrice à chaque appel de fonction -- celle là, je n'ai pas vérifié si l'élimination de temporaires est simple à faire comme c'est le cas dès qu'il y a des sommes ou des vecteurs; je ne sais pas comment ils font dans blitz++, eigen, et cie pour les multiplications de matrices.
Je n'ai pas vérifié non plus si tu avais bien interverti les deux boucles les plus profondes, ni si tu travaillais bien sur des sous-blocs.
PS: sur les archi intel, la MKL est ce qu'il y a de plus rapide, et il est pratiquement impossible de faire mieux.
C'est pour que tout soit aligné dans le cache, j'ai essayer par blocs mais comme je n'ai besoin de le faire que pour des matrices de taille 512 par 512(strassen qui s'arrete quand les matrices font cette taille.), cette methode est plus efficace(a moins que je m'y sois mal pris).
Pour l'instant avec des int j'obtient de tres bonnes perf(7.5 secondes pour des matrices de 8192 par 8192) en parallelisant et avec le SIMD.
Ca marche merci de tes reponses, je vais essayer d'aller voir vers une générique de vectorisation comme tu me l'as conseiller.
En revanche pour l'allocation memoire, elle est indispensable, je vais aller chercher plusieurs fois les elements d'une meme colonne dans le cache ce qui va etre beaucoup plus rapide lorsque tout est aligné dans la memoire.
De plus, meme si je n'ai jamias utiliser boost::aligned_allocator, je ne suis pas sur que cela change grand chose si je dois parcourir les elements de la meme colonne rapidement.
"Sors l'alloc de la boucle, et réutilise le vecteur" est mon message
Quant à l'alignement, c'est pour pouvoir directement manipuler des séquences calées sur les tailles des caches sans avoir à avoir une première boucle de peeling qui peut autrement être nécessaire. Cela ne retirera pas un éventuel besoin de boucle finale à la main.
En effet, je n'avais pas vu la déclaration du vector avec un width dans le for.
Réduire absolument le nombre d'allocations gagnera beaucoup. Donc alloue tout ce que tu as à allouer avant les boucles. Mais je dis ce qui a été dit en fait...
Juste pour apporter ma pierre à l'édifice : je bosse dans une boite ou on fait des programmes qui calculent beaucoup, et dégager les allocations, ça optimise vraiment bien les zones critiques, c'est un fait.
Ah oui, effectivement vous avez raison je vais corriger ca. Merci beaucoup encore! J'ai gagne un facteur 2 sur mes calcul!!
Optimisation multiplication de matrices
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
En recherche d'emploi.
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html