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 :

fonction vide: compilateur optimise ou pas


Sujet :

C++

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 646
    Par défaut fonction vide: compilateur optimise ou pas
    Bonjour,

    Si je fais ca, dans une classe ou en fonction:
    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
    void fonction(char* chaine)
    {
    #ifdef DEBUG
    cout << chaine;
    #endif
    }
     
    // ou bien dans une classe
    void CMaClasse::fonction(char* chaine)
    {
    #ifdef DEBUG
    cout << chaine;
    #endif
    }
     
    // Dans mon code
    fonction();
    pMaClasse->fonction();
    Et que je compile sans definir le DEBUG, en release par exemple. Est-ce que le compilo detecte que la fonction ne fait rien ou pas? Car c'est bien une optimisation de ne pas faire l'appel!

    car techniquement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #undef DEBUG
    fonction();
    // revient a =>
    /* du vide */
    Alors

    PS: je pense que l'on peut compiler en mode asm et regarder si oui ou non on a l'appel, mais je sais pas faire

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Ça dépend si l'optimiseur est activé et si le contenu de la fonction est visible pendant qu'on compile l'appel.

    C'est naturellement le cas pour les fonctions inline, par exemple...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 646
    Par défaut
    Oui pour les fonctions inline.

    Mais dans le cas ou on a des grosses fonctions, ou tout simplement dont c'est pas tres bien d'inliné, je me demandais.

    mais bon ok, donc l'optimiseur detecte les fonctions vides. Merci pour l'info.
    Ils sont fort ces compilos

  4. #4
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Mais il ne la détecte que si il voit son code.
    Donc, pas si elle est dans un autre fichier source... (sauf si la Link-Time Code Generation est activée, bien sûr)
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    A priori, le seul cas où le compilo verrait le code est celui où la fonction est inline (il y a bien les namespaces non nommés et les fonctions statiques du C, mais vous les utilisez dans des headers vous??). Donc tu peux considérer que ça ne fonctionne que si la fonction est inline.

  6. #6
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Si la fonction est dans le même fichier source, le compilo la connait. Il peut même décider de l'inliner sans que tu lui demandes.

    Et en LTCG, le compilo voit toutes les fonctions d'un coup, il peut donc optimiser à fond.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 646
    Par défaut
    ok, bon ben c'est foutu, la fonction est dans un autre source...
    Tant pis perdrai un appel

    Mais sinon c'est vrai en fait, logique puisqu'il compile fichier par fichier...
    Mais... si j'etais un compilo: si je vois que la fonction que je compile prend moins de 'place' en l'inlinant qu'en l'appelant, je l'inlinerai alors, meme si je ne suis pas dans le meme source...
    Puisque quand on fait une fonction inline, il arrive que le compilo ne le fasse pas(il me semble). De la meme maniere est-ce qu'il ne prend pas la decision lui meme d'inliné certaines fonctions non inline(independamment des fichiers sources)?
    Car techniquement, il n'y a aucun mal a faire des fonctions inline.

  8. #8
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    Citation Envoyé par kacedda Voir le message
    Car techniquement, il n'y a aucun mal a faire des fonctions inline.
    En fait, si, il peut y avoir pas mal de problèmes à cause d'un simple inlining de fonction non contrôlé (et pas forcément évident à diagnostiquer si on en est pas conscient).

    Pour une fonction complétement vide je suis d'accord avec toi.

    Maintenant, c'est pas parce que le compilateur arrive à empécher un inline que l'inverse est forcément aussi facile.

    Si je suis un raisonnement :

    Objet A avec f1 inline dans le header et f2 non inline dans le cpp.

    Objet B qui fait un include de A et se sert des deux fonctions.

    Que se passe-t-il si B.cpp est compilé avant A.cpp ?
    B.cpp inclut A.h et voit donc f1. Il peut décider de ne pas l'inliner pour une raison x, y. Seulement pour f2, il ne dispose à ce moment que de la définition. Aucune décision d'inlining ne peux être prise ici.

    Et puis imagine, quand bien même le compilateur arriverait à décider d'inliner une fonction à priori non inline dans un cpp. Si tu modifies cette fonction par la suite, il faudrait qu'il recompile les cpps qui l'utilisent... Du coup les règles de makefiles sont chamboulées.

    C'est pour ça que, sans options particulière, je dirais qu'un compilateur ne fait pas d'optimisation d'inlining dans ce sens.

    Maintenant je me trompe peut-être car je ne tiens ces infos de nulle part.

  9. #9
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    Pour que ca passe les optimisations de compilation à mort:
    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
     
    void function_call(const char* str)
    {
        cout << str;
    }
     
    #ifdef DEBUG
    inline void function(const char* str) { function_call(str); }
    #else
    inline void function(const char* str) {}
    #endif
     
    class CMaClasse
    {
    #ifdef DEBUG
    inline void function(const char* str) { funcation_call(str); }
    #else
    inline void function(const char* str) {}
    #endif
    };
    Mais je conseille vivement un truc... (sans doute dû à de trop nombreuses et fâcheuses expérience du release-mode): Ne JAMAIS virer le code de trace...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    inline void function(const char* str) { if (debug_enabled) function_call(str); }
     
    class CMaClass
    {
    inline void function(const char* str) { if (debug_enabled) function_call(str); }
    };
    Avec un moyen de modifier la valeur de debug_enabled facilement... ca t'enlevera à cout sur quelques épines un jour...
    Le code ne sera pas plus lent en release, de manière visible en tout cas (si le debug_enabled est partagé, il y a de très fortes chances pour qu'il reste longtemps dans le cache mémoire).

  10. #10
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 646
    Par défaut
    Citation Envoyé par NiamorH Voir le message
    Maintenant je me trompe peut-être car je ne tiens ces infos de nulle part.
    haha, ... mais "La logique est [parfois] une source d'information".

    Oui effectivement je n'avais pas pensé a tous ca. Mais bon, je pense qu'il faudrait trouver un expert compilo et de toute facon c'est surement different pour chaque compilo...

    Par contre j'aime bien la solution de nicroman, c'est vraiment super simple en plus!

    Merci a tous pour les infos et precision

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

    Informations professionnelles :
    Activité : aucun

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

    Il faut bien être conscient que, si le compilateur décide de ne pas inliner une fonction pour laquelle on lui a demandé de le faire, c'est généralement parce que la fonction elle-même est impossible à inliner:

    Pense par exemple aux fonctions récursives "classiques" du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void fonction( int i)
    {
       if(i!=0)
           fonction(i-1);
    }
    ...ou, plus discrètes du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    LaClass::~LaClass()
    {
        /* tab est un vecteur de pointeurs de type LaClass ;)
         * le destructeur n'étant pas virtuel (pour lui donner une chance
         * d'etre inliné :P ) */
        for(size_t i=0;i<tab.size();i++)
            delete tab[i];//appel récursif de LaClass::~LaClass() :P
    }
    ou enfin à une fonction virtuelle, qui ne peut jamais être inlinée, car le polymorphisme a, justement, pour but de décider quelle fonction sera appelée... lors de l'exécution

    Enfin, il peut, techniquement, y avoir un réel mal à avoir toutes les fonctions inlines:

    Comme indiqué plus haut, le polymorphisme et la récursivité (je passe sur la récursivité finale ) ne peuvent pas être employés.

    Mais, en plus, il est possible de se trouver dans des circonstances dans lesquelles ont préférera un exécutable "léger" à un exécutable "rapide" (l'éternel compromis entre la rapidité et la taille de l'exécutable ) or, si tu viens à inliner les plus grosses fonctions, et qu'elles sont, de plus, régulièrement appelées, tu vas littéralement voir "exploser" la taille de ton exécutable
    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

  12. #12
    Membre émérite

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    717
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Il faut bien être conscient que, si le compilateur décide de ne pas inliner une fonction pour laquelle on lui a demandé de le faire, c'est généralement parce que la fonction elle-même est impossible à inliner.
    Je ne vois aucune fonction qui ne puisse pas être inliner, dans l'absolu.

    Pense par exemple aux fonctions récursives "classiques" du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void fonction( int i)
    {
       if(i!=0)
           fonction(i-1);
    }
    Si cette fonction est appelée en lui passant une constante, par exemple, il y a de forte chances que le compilateur inline l'appel et le remplace par rien du tout. En fait, le compilateur ne choisi pas d'inliner ou pas une fonction, il choisi d'inliner ou pas tel ou tel appel de la fonction.

    ou enfin à une fonction virtuelle, qui ne peut jamais être inlinée, car le polymorphisme a, justement, pour but de décider quelle fonction sera appelée... lors de l'exécution
    Même un appel à une fonction virtuelle peut être inliner, si le compilateur arrive à déterminer, par le contexte, le type statique de l'objet.

    Mais, en plus, il est possible de se trouver dans des circonstances dans lesquelles ont préférera un exécutable "léger" à un exécutable "rapide" (l'éternel compromis entre la rapidité et la taille de l'exécutable )
    Inliner ne veut pas forcement dire exécutable plus lourd, au contraire, inliner toutes les petites fonctions genre setter/getter va alléger l'executable, et même parfois inliner des grosse fonctions peut faire gagner en taille grâce aux optimisations qu'offre la connaissance du contexte d'appel.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Citation Envoyé par Sylvain Togni Voir le message
    Je ne vois aucune fonction qui ne puisse pas être inliner, dans l'absolu.
    Dans l'absolu, je te l'accorde, dans la pratique, il en est (souvent)autrement
    Si cette fonction est appelée en lui passant une constante, par exemple, il y a de forte chances que le compilateur inline l'appel et le remplace par rien du tout. En fait, le compilateur ne choisi pas d'inliner ou pas une fonction, il choisi d'inliner ou pas tel ou tel appel de la fonction.
    et, dans tous les cas ou cette fonction reçoit une variable définie par calcul ou par introduction de l'utilisateur, le compilateur ne saura pas s'il doit l'inliner 3 fois ou 9 ou ...100
    Même un appel à une fonction virtuelle peut être inliner, si le compilateur arrive à déterminer, par le contexte, le type statique de l'objet.
    ce qui est rarement le cas quand tu met le polymorphisme en branle...

    L'intérêt, justement, du polymorphisme réside dans le fait que tu sais quel sera le type "de base" des éléments que tu va insérer, sans savoir précisément quel sera leur type particulier, et de pouvoir faire, pourquoi pas, cohabiter des avions, des bateaux et des voitures sous le vocable "véhicules"
    Inliner ne veut pas forcement dire exécutable plus lourd, au contraire, inliner toutes les petites fonctions genre setter/getter va alléger l'executable, et même parfois inliner des grosse fonctions peut faire gagner en taille grâce aux optimisations qu'offre la connaissance du contexte d'appel.
    Et c'est bien pour cela que j'ai précisé que je parlais là de fonctions lourdes et dont l'appel était fréquent ... Quitte à faire la citation, tu aurais au moins pu avoir l'honnêteté intellectuelle de faire la citation complète
    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

  14. #14
    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
    Pour générer le ASM ajouter l'option FA :
    Dans VS 2005 : Propreties -> C++ -> Ouput Files -> Assembler Output

  15. #15
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    Citation Envoyé par koala01 Voir le message
    l'éternel compromis entre la rapidité et la taille de l'exécutable
    A mon avis, ce débat ne sera pas éternel. Les capacités mémoire et les débits internet explosent eux aussi, bien plus vite que la taille de simples éxécutables. Ce sont les ressources qui aujourd'hui pèsent le plus lourd.

Discussions similaires

  1. compilateur ne reconnait pas une fonction existante
    Par loutsa dans le forum GTK+ avec C & C++
    Réponses: 2
    Dernier message: 02/11/2008, 10h40
  2. Optimisation : fonction vide ou test
    Par bolhrak dans le forum C++
    Réponses: 2
    Dernier message: 15/07/2006, 19h31
  3. [Compilateur] Optimisation des conditions
    Par Pedro dans le forum Langage
    Réponses: 2
    Dernier message: 16/06/2004, 13h49
  4. Le compilateur ne trouve pas glut32.dll
    Par Vathal dans le forum GLUT
    Réponses: 3
    Dernier message: 26/01/2004, 12h34
  5. Fonction vide
    Par vagabon dans le forum Autres éditeurs
    Réponses: 9
    Dernier message: 29/07/2003, 18h23

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