La correction de constance peut-elle améliorer les performances?

92

J'ai lu à plusieurs reprises que l'application de const-correctness dans votre code C ou C ++ n'est pas seulement une bonne pratique en ce qui concerne la maintenabilité, mais cela peut également permettre à votre compilateur d'effectuer des optimisations. Cependant, j'ai également lu le contraire: cela n'affecte pas du tout les performances.

Par conséquent, avez-vous des exemples où la correction de const peut aider votre compilateur à améliorer les performances de votre programme?

shuhalo
la source
50
La correction de la constance est l'une des meilleures pratiques en matière de maintenabilité. Si votre code C ++ n'est pas correct, c'est essentiellement un tas de merde, en attente d'un désastre. Il n'est pas destiné à affecter les performances.
2
@Neil Butterworth: malheureusement l'inverse n'est pas vrai.
Bêta du
6
Voici un exemple où les constperformances ont fait une différence: stackoverflow.com/questions/1121791/… . Mais c'était essentiellement une question de qualité de mise en œuvre. constn'a pas déterminé si le compilateur pouvait légalement effectuer l'optimisation, il s'est juste produit que la version du compilateur n'a pas réussi à le faire quand il manquait.
Steve Jessop
3
Je suis sûr que "morgennebel" a raté un "seulement" dans la première phrase: cela a beaucoup plus de sens avec "n'est pas seulement une bonne pratique".
IanH
2
@IanH Oui, j'ai pensé à ça. Mais le PO a eu amplement le temps de clarifier. Je suis vraiment impressionné par les gens qui posent des questions et disparaissent simplement.

Réponses:

77

constl'exactitude ne peut pas améliorer les performances car const_castet mutablesont dans le langage, et permet au code d'enfreindre les règles de manière conforme. Cela devient encore pire en C ++ 11, où vos constdonnées peuvent par exemple être un pointeur vers a std::atomic, ce qui signifie que le compilateur doit respecter les modifications apportées par d'autres threads.

Cela dit, il est trivial pour le compilateur de regarder le code qu'il génère et de déterminer s'il écrit réellement dans une variable donnée, et d'appliquer les optimisations en conséquence.

Cela dit, l' constexactitude est une bonne chose en ce qui concerne la maintenabilité. Sinon, les clients de votre classe pourraient briser les membres internes de cette classe. Par exemple, considérez le standard std::string::c_str()- s'il ne pouvait pas renvoyer une valeur const, vous seriez en mesure de visser avec le tampon interne de la chaîne!

Ne l'utilisez pas constpour des raisons de performances. Utilisez-le pour des raisons de maintenabilité.

Billy ONeal
la source
31
"vous seriez capable de visser avec le tampon interne de la chaîne!" - surtout, vous seriez capable de visser accidentellement avec le tampon interne. Les erreurs du compilateur dues à constsont des panneaux indiquant, "vous faites quelque chose de stupide".
Steve Jessop
4
... et const-cast sont des panneaux indiquant: "l'auteur de ce code essaie de faire quelque chose d'intelligent" ;-)
Steve Jessop
5
@Steve Jessop - ou const-cast sont des panneaux indiquant "J'essaye de boulonner un paquet de code const-correct à un non-const-correct, et je ne peux pas réparer l'un ou l'autre". Ce qui, laissez-moi vous dire, n'est en aucun cas intelligent, juste ennuyeux.
Michael Kohne
7
@Michael - oui, bon point. Peut-être que le panneau original n'est pas "tu fais quelque chose de stupide", mais plutôt "quelqu'un fait quelque chose de stupide".
Steve Jessop
Godbolt et Arduino m'ont dit que la correction des constats n'est pas seulement pour le plaisir.
dgrat le
31

Oui il peut.

La plupart des consts sont purement pour le bénéfice du programmeur et n'aident pas le compilateur à optimiser car il est légal de les rejeter et ainsi ils ne disent rien d'utile au compilateur pour l'optimisation. Cependant, certains consts ne peuvent pas être jetés (légalement) et ceux-ci fournissent au compilateur des informations utiles pour l'optimisation.

À titre d'exemple, l'accès à une variable globale définie avec un consttype peut être inséré alors qu'une variable sans consttype ne peut pas être insérée car elle peut changer au moment de l'exécution.

https://godbolt.org/g/UEX4NB

C ++:

int foo1 = 1;
const int foo2 = 2;

int get_foo1() {
    return foo1;
}

int get_foo2() {
    return foo2;
}

asm:

foo1:
        .long   1
foo2:
        .long   2
get_foo1():
        push    rbp
        mov     rbp, rsp
        mov     eax, DWORD PTR foo1[rip] ; foo1 must be accessed by address
        pop     rbp
        ret
get_foo2():
        push    rbp
        mov     rbp, rsp
        mov     eax, 2 ; foo2 has been replaced with an immediate 2
        pop     rbp
        ret

En termes pratiques, gardez à l'esprit que si cela constpeut améliorer les performances, dans la plupart des cas, ce ne sera pas le cas ou ce sera le cas, mais le changement ne sera pas perceptible. La principale utilité de constn'est pas l'optimisation.


Steve Jessop donne un autre exemple dans son commentaire sur la question initiale qui soulève quelque chose qui mérite d'être mentionné. Dans une portée de bloc, il est possible pour un compilateur de déduire si une variable sera mutée et d'optimiser en conséquence, indépendamment de const, car le compilateur peut voir toutes les utilisations de la variable. En revanche, dans l'exemple ci-dessus, il est impossible de prédire si foo1sera muté car il pourrait être modifié dans d'autres unités de traduction. Je suppose qu'un ultra-compilateur sensible hypothétique pourrait analyser un programme entier et déterminer s'il est valide pour un accès en ligne à foo1... mais les vrais compilateurs ne le peuvent pas.

Praxéolitique
la source
@ericcurtin C'est pourquoi je n'ai pas mentionné le compilateur dans la réponse. Normalement, lors de la publication de l'assembly généré, je m'assurerais d'indiquer le compilateur et la version, mais c'est une optimisation que chaque compilateur d'optimisation majeur effectuera, donc je ne voulais pas donner l'impression que cela était particulier à un compilateur.
Praxeolitic
1
@Acorn Voici le même exemple mais avec un objet de classe: godbolt.org/z/R-Zfgc . De plus, les variables de l'exemple ont un lien externe.
Praxeolitic
6

d'après mon expérience, non

Pour les variables scalaires, le compilateur est capable de déterminer chaque fois que la valeur est modifiée et d'effectuer lui-même l'optimisation nécessaire.

Pour les pointeurs de tableau, l'exactitude de const ne garantit pas que les valeurs sont vraiment constantes en présence de problèmes potentiels d'alias. Par conséquent, le compilateur ne peut pas utiliser le modificateur const seul pour effectuer des optimisations

si vous recherchez une optimisation, vous devriez envisager __restrict__des modificateurs / attributs de fonction spéciaux: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

Anycorn
la source