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

C++ Discussion :

Performance déclaration locale de variable


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Par défaut Performance déclaration locale de variable
    Salut,

    J'ai quelques questions qui me turlupinent à chaque fois que j'écris du code avec des impératifs de performance :

    - est ce qu'une variable déclarée localement dans une boucle a un risque d'être moins rapide qu'une variable déclarée à l'extérieur.

    - dans une boucle for (i = 0; i < monVecteur.size(); i++) est ce qu'on perd un peu de temps à évaluer la fonction size() par rapport à la mettre dans une variable (si elle ne varie pas) ?

    - de manière plus générale si j'utilise plusieurs fois une valeur de variable constante que j'obtiens avec un appel de fonction et/ou une indirection dois-je stocker localement cette variable ?

    Merci !

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    La méthode size() est de toutes manières faite pour être en temps d'exécution constant, ce qui fait que je peux déjà t'assurer que tu ne prend pas plus de temps à obtenir le résultat avec 100 000 éléments qu'avec 10.

    Et il me semble même que la méthode est déclarée inline (bien que je ne puisse en jurer), et, si c'est bel et bien le cas, il n'y aura pas de différences entre le fait de prendre la valeur une fois pour toute en dehors de la boucle et celui de rappeler la méthode à chaque fois.

    Quoi qu'il en soit, faut il rappeler que dans plus de 90% des cas, ce genre d'optimisation arrive trop tôt et qu'il vaut mieux commencer par voir s'il n'y a pas moyen d'optimiser l'algorithme/les structures de manière a s'éviter des itérations inutiles
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre éclairé
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Quoi qu'il en soit, faut il rappeler que dans plus de 90% des cas, ce genre d'optimisation arrive trop tôt et qu'il vaut mieux commencer par voir s'il n'y a pas moyen d'optimiser l'algorithme/les structures de manière a s'éviter des itérations inutiles
    Certes, mais quitte à écrire quelque chose, autant que ce soit pas trop mal la première fois...

  4. #4
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par tnarol Voir le message
    Certes, mais quitte à écrire quelque chose, autant que ce soit pas trop mal la première fois...
    Oui, si par "pas trop mal" tu envisages les choses sous l'angle de l'algorithme.

    Si tu fais bien ton travail en utilisant des noms de variables non concurrents et explicites, et que tu te rend compte que, malgré le fait que ton algorithme est "aussi optimisé que faire se peut", il faut encore essayer de grapiller quelques cycles d'horloges, le fait de sortir la fonction de la boucle ne devrait pas poser de problème, et tu sera libre de faire les tests de perfs pour t'assurer du fait que cela change quelque chose ou non
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre chevronné Avatar de themadmax
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    446
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 446
    Par défaut
    Bonne question, et d'après la littérature il est conseillé de déclarer une variable au plus tard dans le code.

    Testons :
    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    #include <iostream>
    #include <windows.h>
     
    #define COUNT 100
    int tab[COUNT];
     
    void func1()
    {
    	for (int i=0; i<COUNT; i++)
    	{
    		int b = tab[i];
    		if ( b == 0 )
    			b++;
    	}
    }
     
    void func2()
    {
    	int b;
    	for (int i=0; i<COUNT; i++)
    	{
    		b = tab[i];
    		if ( b == 0 )
    			b++;
    	}
    }
     
    int main()
    {
    	memset( tab, 0, COUNT );
    	__int64 start, stop;
     
    	QueryPerformanceCounter((LARGE_INTEGER*)&start);
    	func1();
    	QueryPerformanceCounter((LARGE_INTEGER*)&stop);
    	std::cout << (stop - start) << std::endl;
     
    	QueryPerformanceCounter((LARGE_INTEGER*)&start);
    	func2();
    	QueryPerformanceCounter((LARGE_INTEGER*)&stop);
    	std::cout << ( stop - start ) << std::endl;
    }
    J'ai fait plusieurs tests avec VS2005 (Release) et c'est a peut prés pareil, pour les deux fonctions !
    Il faudrai jeter un coup d'oeil dans le code ASM généré.

  6. #6
    Invité
    Invité(e)
    Par défaut
    J'ai fait le même test chez moi :
    Code c++ : 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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    #include <iostream>
    #include <time.h>
     
    #define COUNT 100000000
    int tab[COUNT];
     
    void func1()
    {
        for (int i=0; i<COUNT; i++)
        {
            int b = tab[i];
            if ( b == 0 )
                b++;
        }
    }
     
    void func2()
    {
        int b;
        for (int i=0; i<COUNT; i++)
        {
            b = tab[i];
            if ( b == 0 )
                b++;
        }
    }
     
    int main()
    {
        memset( tab, 0, COUNT );
     
        clock_t start, stop;
     
        start = clock();
        func1();
        stop = clock();
        std::cout << (unsigned int)(stop - start) << std::endl;
     
        start = clock();
        func2();
        stop = clock();
        std::cout << (unsigned int)( stop - start ) << std::endl;
     
        return 0;
    }
    Avec g++ 4.2.3, les résultats sont les suivants:
    func1 -> 1090000
    func2 -> 790000

  7. #7
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par themadmax Voir le message
    Bonne question, et d'après la littérature il est conseillé de déclarer une variable au plus tard dans le code.
    Ca n'a pas grand chose à voir avec un problème de rapidité d'exécution du cycle normal.

    Par contre, si tu fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void f1(params..)
    {
      MaClasseQuiPrendsDuTempsALaConstruction c(params..)
      if (test_sur_une_valeur_indep_de_c) return;
      ...
    }
     
    void f2(params..)
    {
      if (test_sur_une_valeur_indep_de_c) return;
      MaClasseQuiPrendsDuTempsALaConstruction c(params..)
      ...
    }
    Alors f2 est plus rapide que f1, qui exécute un constructeur et un destructeur en plus. Par contre, si c est un int, le temps d'exécution sera probablement identique (car un int est simplement réservé sur la pile - il n'y a ni constructeur ni destructeur à appeler).

    De manière générale, plus tu attends pour déclarer une variable, plus tu a de chance que cette déclaration ne soit pas nécessaire - d'où la recommandation de la déclarer le plus tard possible.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  8. #8
    Inactif  
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    743
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 743
    Par défaut
    J'apporte mon petit grain de sel:

    Citation Envoyé par tnarol Voir le message
    - est ce qu'une variable déclarée localement dans une boucle a un risque d'être moins rapide qu'une variable déclarée à l'extérieur.
    Je ne pense pas. En tout cas, c'est tellement plus pratique et élégant de déclarer une variable locale à l'intérieur.
    Exception plus que probable: si cette variable locale est une classe avec un constructeur...

    Citation Envoyé par tnarol Voir le message
    - dans une boucle for (i = 0; i < monVecteur.size(); i++) est ce qu'on perd un peu de temps à évaluer la fonction size() par rapport à la mettre dans une variable (si elle ne varie pas) ?
    J'avais fait des essais du genre y'a quelques années (principalement avec le compilateur Intel sous Windows, plus rapide que GCC ou Visual d'après mes benchs).
    J'en étais venu à la conclusion, qu'il valait mieux stocker le résultat dans une variable. J'aurais pensé le contraire, car j'estimais que l'inline jouerait à plein pour des fonctions du genre de size ou une simple addition, et pourtant...
    Depuis j'ai pris l'habitude d'écrire les boucles dans le genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for (int i=0, imax=vec.size(); i<imax; ++i) ...
    for (int i=0, imax=n+10;       i<imax; ++i) ...

  9. #9
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Charlemagne Voir le message
    J'apporte mon petit grain de sel:
    Tant qu'il ne fait pas gripper la machine...
    Je ne pense pas. En tout cas, c'est tellement plus pratique et élégant de déclarer une variable locale à l'intérieur.
    Exception plus que probable: si cette variable locale est une classe avec un constructeur...
    Et encore...

    Il est peut être alors utile de savoir si la variable "temporaire" utilise tout le temps les mêmes valeurs ou non, et, dans la négative, il faut alors comparer les performances des constructions/destructions successives avec celles des (ré)initialisations à envisager pour permettre à cette variable de fonctionner avec les bonnes valeurs...

    Et je parle ici de performances uniquement, car, en ce qui concerne le code à utiliser pour la réinitialisation, je préférerais me contenter d'un appel au constructeur et de la destruction automatique de la variable

    Quand on dit que rien n'est blanc ou noir
    J'avais fait des essais du genre y'a quelques années (principalement avec le compilateur Intel sous Windows, plus rapide que GCC ou Visual d'après mes benchs).
    J'en étais venu à la conclusion, qu'il valait mieux stocker le résultat dans une variable. J'aurais pensé le contraire, car j'estimais que l'inline jouerait à plein pour des fonctions du genre de size ou une simple addition, et pourtant...
    Depuis j'ai pris l'habitude d'écrire les boucles dans le genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for (int i=0, imax=vec.size(); i<imax; ++i) ...
    for (int i=0, imax=n+10;       i<imax; ++i) ...
    Cela implique de se poser quelques questions de base (du fait qu'il ne faut jamais se fier à un bench que l'on n'a pas truqué soi-même )
    • Pourrais-tu, ne serait-ce qu'approximativement, nous dire il y a combien de temps
    • Quelle était la version du compilateur intel
    • As tu réeffectué les tests avec la version actuelle
    • Etait-ce suffisemment significatif que pour justifier l'utilisation en dehors de situations où les temps d'exécutions sont réellement critiques (AKA ou le moindre cycle d'horloge compte)
    • sans doute une ou l'autre à laquelle je n'ai pas pensé...


    EDIT par contre, j'ai toujours eu horreur de rencontrer deux instructions différentes dans l'une des parties des boucles...
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #10
    Inactif  
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    743
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 743
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Cela implique de se poser quelques questions de base (du fait qu'il ne faut jamais se fier à un bench que l'on n'a pas truqué soi-même )
    • Pourrais-tu, ne serait-ce qu'approximativement, nous dire il y a combien de temps
    • Quelle était la version du compilateur intel
    • As tu réeffectué les tests avec la version actuelle
    • Etait-ce suffisemment significatif que pour justifier l'utilisation en dehors de situations où les temps d'exécutions sont réellement critiques (AKA ou le moindre cycle d'horloge compte)
    • sans doute une ou l'autre à laquelle je n'ai pas pensé...
    Y'a peut-être environ 3-4 ans, plus que probablement avec la version 8.0.X ou 8.1.X du compilateur d'Intel (ICL).
    Intel a certes sorti les version 9 et 10 depuis, mais ça ne fait probablement aucune différence. Je préfère a propos la version 8.1 aux récentes, car la version 8.1 obéit au doigt et à l'oeil aux consignes inline, alors que depuis les autres versions ne font que ce qu'elles veulent.
    Dans mes tests, c'était pas négligeable pour des boucles à petit contenu. C'est clair qu'il y'a d'autres moyens autrement plus efficaces pour optimiser les boucles (déroulement bien pensé, calculs SIMD...)
    Citation Envoyé par koala01 Voir le message
    EDIT par contre, j'ai toujours eu horreur de rencontrer deux instructions différentes dans l'une des parties des boucles...
    Faut pas en abuser de la double instruction, mais je trouve ça sympa dans certains cas pour pas surcharger le contenu de la boucle, du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    for (iterator it=X.begin(), end=X.end(); it!=end; ++it) ...
     
    for (int i=0, j=n-1; i<n; ++i, --j) ...//double balayage avant-arrière
     
    //copie
    for (float *p=&X[0], *q=&Y[0], *end=X[n]; p!=end; ++p, ++q)
      *q=*p;

    Déclarer une variable imax comme dans l'exemple de mon message précédent, ne mange pas de pain, alors dans le doute sur la performance, autant aider le ou les compilateurs.
    Car on est sûrement d'accord pour dire qu'au moins ça ne nuira pas aux performances...

Discussions similaires

  1. Réponses: 3
    Dernier message: 21/08/2013, 17h54
  2. Utiliser la valeur d'un spinner lors de la déclaration d'une variable locale
    Par Jiggazzzzz dans le forum Composants graphiques
    Réponses: 4
    Dernier message: 05/12/2011, 09h31
  3. Réponses: 4
    Dernier message: 22/03/2006, 15h42
  4. déclaration de path, variables et autres...
    Par minusette dans le forum Langage
    Réponses: 3
    Dernier message: 21/02/2006, 15h46
  5. déclaration d'une variable
    Par ouldfella dans le forum Composants VCL
    Réponses: 8
    Dernier message: 20/10/2005, 18h21

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