IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Optimisation Vitesse d'Exécution Calcul matriciel


Sujet :

Langage C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 91
    Points : 50
    Points
    50
    Par défaut Optimisation Vitesse d'Exécution Calcul matriciel
    Bonjour à toutes et à toutes.

    Pour un algorithme de traitement d'informations, je dois appliquer sur un tableau 600x600 un filtre de corrélation 21x21

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    int demiTaille = 10;
    for(int n=0; n< 600; ++n)
        for(int m=0; m<600; ++m)
        {
            int uBegin = std::max(0, n - demiTaille );
            int uEnd = std::min(600- 1, n + demiTaille );
            int vBegin = std::max(0, m - demiTaille );
            int vEnd = std::min(600- 1, m + demiTaille );
            double temp = 0.0;
            for(int u=uBegin; u<=uEnd; ++u)
                for(int v=vBegin; v<=vEnd; ++v)
                    temp += abs(tabInitial[u][v]) * filter[demiTaille + u - n][demiTaille + v - m];
            tabFinal[n][m] = temp;
        }
    Le problème est que l'exécution de cette partie dure 0.4 secondes, ce qui est trop long pour mon application.

    Est ce que quelqu'un aurait des solutions d'optimisation.

    Merci d'avance

  2. #2
    Membre confirmé Avatar de Nhaps
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    350
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2011
    Messages : 350
    Points : 603
    Points
    603
    Par défaut
    Bonjour,

    est ce que tes conteneurs sont des vectors ?
    Windev 23 - SQL SERVER - PHP
    Play : TFT - Jeux indé

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 91
    Points : 50
    Points
    50
    Par défaut
    alors au depart oui j'ai utiliser des vector<vector<double>>, mais l'exécution était alors de 4.2s.
    donc j'ai essayé avec des double**, et la je passe à 0.4s

    je n'ai pas essayer de faire un vector<double> de taille 600x600 par contre...

  4. #4
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    576
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 576
    Points : 1 528
    Points
    1 528
    Par défaut
    essaye

    Avec un double**, toutes tes données ne sont pas contiguë en mémoire. Avec un vector de taille 600*600 elle le seront et les accès mémoire seront beaucoup plus rapide.

    Je te renvois là, ça pourrait t'aider:
    http://www.developpez.net/forums/d10...cteur-vecteur/
    La perfection est atteinte, non pas lorsqu’il n’y a plus rien à ajouter, mais lorsqu’il n’y a plus rien à retirer. - Antoine de Saint-Exupéry

  5. #5
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Citation Envoyé par pyros Voir le message
    essaye

    Avec un double**, toutes tes données ne sont pas contiguë en mémoire. Avec un vector de taille 600*600 elle le seront et les accès mémoire seront beaucoup plus rapide.
    Non, c'est pas garantie en C++98 (par contre toute les implémentations que je connaissent le sont oui )
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  6. #6
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    une idée à tester, bien qu'il y a de grandes chances pour que le compilateur optimise ça lui-même, mais ne sait-on jamais:
    - les tests d'arrêt de boucle. Ils sont appelés à chaque itération. Les == et != sont plus rapide que les <, >, <= ou >=

    Après, moi je suis sûr que dans ce cas là, ce sera plus rapide avec des vector à une dimension et un iterateur, qu'avec un vector à une dimension et accès avec indice. Certainement pas un gain énorme, mais ce sera toujours ça de pris.

    Et puis après, il faut chercher du côté de l'utilisation de threads, si tu as plusieurs cores ou plusieurs processeurs en particulier. Et surtout si tu peux trouver une méthode pour pouvoir permettre cela. Par exemple en découpant ta matrice en sous-matrices et appliquant le filtre dans des processus séparés, ce genre de choses.

    Sinon iol doit bien y avoir des libs qui font ce genre de choses déjà non?
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par r0d Voir le message
    Sinon iol doit bien y avoir des libs qui font ce genre de choses déjà non?
    +++

    ** Dans le genre d'idée qui te feront gagner quelques pouillèmes (peu quantifiables?) : garnir tes lignes à gauches et à droites de 10 cases à 0 pour éviter les std::max/min. Ou alors, couper la boucle for pour gérer l'intérieur (n/m de 10 à 590) et gérer les bords séparément toujours pour éviter ces min/max inutiles.

    ** int demiTaille = 10; => int const demiTaille = 10; Ca ne fera rien gagner en vitesse mais c'est probablement plus exact dans ton code

    ** Cette dbouble boucle là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for(int u=uBegin; u<=uEnd; ++u)
         for(int v=vBegin; v<=vEnd; ++v)
               temp += abs(tabInitial[u][v]) * filter[demiTaille + u - n][demiTaille + v - m];
    Elle peut être exprimée en fonction de l'itération précédente (faire attention à l'impact du calcul numérique ??)

    ** (je ne sais pas si c'est encore vrai) : passer de double en int en supposant que tes grandeurs peuvent être représentées par un entier (modulo un coef de proportion)

  8. #8
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    576
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 576
    Points : 1 528
    Points
    1 528
    Par défaut
    Non, c'est pas garantie en C++98 (par contre toute les implémentations que je connaissent le sont oui )
    Plus par oubli que par volonté. D'ailleurs, certaines interprétations de la sainte norme affirment que la contigüité est sous-entendu.

    Cependant, le std::vector est tellement utilisé en tant que wrapper entre container C++ et fonction C classique (comme read/write) que si un jour quelqu'un s'amusait à sortir une implémentation différente, il n'aurait pas beaucoup de succès
    La perfection est atteinte, non pas lorsqu’il n’y a plus rien à ajouter, mais lorsqu’il n’y a plus rien à retirer. - Antoine de Saint-Exupéry

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 91
    Points : 50
    Points
    50
    Par défaut
    merci pour toutes ses réponses, quel succès !

    d'habitude j'utilise souvent les conteneurs tel que vector, c'est juste la que c'était plus rapide.
    j'ai commencer à implémenter un vector<double> 600x600.
    en faisant juste cela je passe à 1.2s, ce qui est toujours plus long qu'avec mon double**, mais je vais utiliser les messages précédents pour essayer d'affiner mon code et donnerai ma meilleure solution selon ce que je trouve.

    concernant le const demiTaille = 10;
    en fait non je ne peux pas le mettre en const, je l'ai mis la pour la compréhension du code montré, mais en fait cette variable est calculée en amont en fonction de certains paramètres propres à chaque instance de ma classe (mais merci pour l'intention ).

    je vous tiens, au courant, tout en restant ouvert à toute proposition !

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 91
    Points : 50
    Points
    50
    Par défaut
    j'ai essayé de réduire mon algo à 10-590 et ainsi enlever les min et max, aucun changement à l'horizon.
    je ne l'avais pas fait mais j'ai aussi mis "filter" en vector 1D.

    j'ai aussi mi un iterator pour les vector "filter" et "tabFinal".
    je ne l'ai pas fait pour tabInitial, car lors du calcul je n'utilise pas les valeurs contiguës donc je ne suis pas certain du résultat

    mon temps est maintenant à 1.5s, toujours inférieur au double**, avec le code suivant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    std::vector<double>::iterator iteratorFinal = m_resFinal.begin();
    for(int n=halfSizeFilter; n!=nbPixV-halfSizeFilter; ++n)
    {
    	int index = n * nbPixH;
    	for(int m=halfSizeFilter; m!=nbPixH-halfSizeFilter; ++m)
    	{
    		int uBegin = n - halfSizeFilter;
    		int uEnd = n + halfSizeFilter;
    		int vBegin = m - halfSizeFilter;
    		int vEnd = m + halfSizeFilter;
    		double temp = 0.0;
    		std::vector<double>::const_iterator iterFilter = diskFilter.begin();
    		for(int u=uBegin; u!=uEnd+1; ++u)
    		{
    			int index2 = u * nbPixH;
    			int indexF = (halfSizeFilter + u - n) * sizeFilter;
    			for(int v=vBegin; v!=vEnd+1; ++v)
    			{
    				temp += abs(m_res[index2 + v]) * (*iterFilter);
    				++iterFilter;
    			}
    		}
    		maxResFinal = std::max(maxResFinal, temp);
    		*iteratorFinal = temp;
    		++iteratorFinal;
    	}
    }
    Par contre la j'ai une erreur dans mon résultat final à cause d'un des deux itérator

    @3DArchi :
    Elle peut être exprimée en fonction de l'itération précédente (faire attention à l'impact du calcul numérique ??)
    Je ne vois pas trop ce que tu veux dire...

  11. #11
    screetch
    Invité(e)
    Par défaut
    alloue 620 au lieu de 600 pour te débarasser des cas particuliers

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 91
    Points : 50
    Points
    50
    Par défaut
    Citation Envoyé par screetch Voir le message
    alloue 620 au lieu de 600 pour te débarasser des cas particuliers
    je sais, pour le moment je restreint mon parcours à 10-590, si je dois allouer à 620, ça va me faire un paquet de modifs dans le code, et pour le moment je me concentre déjà sur l'optimisation de cette partie

  13. #13
    screetch
    Invité(e)
    Par défaut
    dacodac.
    des instructions SSE?

  14. #14
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    on ne boucle *jamais* sur les valeurs d'un filtre ...
    Ensuite 21x21, ca commence a faire, et je pense que tu irais bcp plus vite a faire un coup de FFT puis de FFTI avec FFTW.

    Sinon dans l'ordre :
    - alignement de la memoire sur la taille des lignes de caches
    - paddign en fin de ligne
    - vector<vector> a remplacé par un tableau NRC contigu
    - deroule la boucle du filtrage entierement
    - SSE2
    - OpenMP

  15. #15
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    576
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 576
    Points : 1 528
    Points
    1 528
    Par défaut
    Je pense que Joel F a tout résumé.

    Et si les perf te suffisent toujours pas => CUDA/Shader. Mais là c'est une autre histoire.
    La perfection est atteinte, non pas lorsqu’il n’y a plus rien à ajouter, mais lorsqu’il n’y a plus rien à retirer. - Antoine de Saint-Exupéry

  16. #16
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    What about utiliser le GPU?
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  17. #17
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 91
    Points : 50
    Points
    50
    Par défaut
    je n'ai encore jamais fait de programmation GPU, mais j'avais songé que ce serait peu être une solution à moyen terme, mais je n'ai pas forcément le temps d'appréhender cette programmation si les perfs ne sont pas au rendez-vous!

  18. #18
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par r0d Voir le message
    What about utiliser le GPU?
    pas pour 600x600 pauvres valeurs ... tu va payer 100000 fois le temps de trasnfert et avoir une acceleration moisie.

  19. #19
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    J'avais pas vu ce poste :

    Citation Envoyé par r0d Voir le message
    une idée à tester, bien qu'il y a de grandes chances pour que le compilateur optimise ça lui-même, mais ne sait-on jamais:
    - les tests d'arrêt de boucle. Ils sont appelés à chaque itération. Les == et != sont plus rapide que les <, >, <= ou >=
    Si c'est vrai, c'est qu'il est temps pour toi de changer de compilateur. Ces micro-optimisations n'ont absolument aucun effet.

    Citation Envoyé par r0d Voir le message
    Après, moi je suis sûr que dans ce cas là, ce sera plus rapide avec des vector à une dimension et un iterateur, qu'avec un vector à une dimension et accès avec indice. Certainement pas un gain énorme, mais ce sera toujours ça de pris.
    Non, ca sera plus rapide avec un tableau 2d contigu acceder via des [][] en notation NRC. Et en general, iterateur , pointeur == meme vitesse.

  20. #20
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Joel F Voir le message
    notation NRC
    Et pour ceux qui ne parle pas le Joel couramment , NRC ça veut dire quoi

Discussions similaires

  1. [Débutant] Optimiser la vitesse d'exécution
    Par horemheb dans le forum VB.NET
    Réponses: 2
    Dernier message: 02/08/2013, 10h40
  2. Optimisation de calcul matriciel
    Par maxi_simo dans le forum MATLAB
    Réponses: 3
    Dernier message: 20/03/2013, 12h53
  3. Optimisation de boucles via calcul matriciel
    Par HAL-9000 dans le forum MATLAB
    Réponses: 12
    Dernier message: 06/03/2010, 21h53
  4. Calcul de la vitesse d'exécution d'un prog.
    Par fred61 dans le forum Débuter
    Réponses: 4
    Dernier message: 10/08/2009, 17h14
  5. Calcul Matriciel en PL/SQL
    Par PpPool dans le forum PL/SQL
    Réponses: 4
    Dernier message: 02/02/2004, 10h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo