9
votes

Utilisation de volatilse pour empêcher l'optimisation du compilateur dans le code de référence d'analyse comparative?

Je crée un petit programme Mesurez la différence de performance entre les conteneurs de types boost :: partage_ptr et boost :: intrusion_ptr . Afin d'empêcher le compilateur d'optimiser la copie, je déclare la variable comme volatile. La boucle ressemble à ceci: xxx

Le reste du code peut être trouvé ici: Main.Cpp .

  • utilisera des volatiles ici empêchant le compilateur d'optimiser la copie?
  • Y a-t-il des pièges qui peuvent invalider les résultats?

    mise à jour

    en réponse à @Neil Butterworth. Même lors de l'utilisation de la copie, il me semble toujours que le compilateur pouvait facilement éviter la copie: xxx

c++

9 commentaires

Utilise -O0 et les drapeaux -g dans le compilateur ne fonctionnent pas? Je ne pense pas que l'utilisation de volatiles est la bonne approche ici.


@RC au lieu de profilage avec -O0 Vous pouvez simplement deviner l'impact de la performance à la place. Le résultat n'a de même aucune incidence sur un scénario réaliste.


@RC Je ne suis pas sûr. Je sais que les optimisations comme le RVO vont frapper même lorsque vous utilisez -O0 (voir Stackoverflow.com/questions/4767620/... ).


Si le constructeur de copie a des effets secondaires, le compilateur est-il même autorisé à optimiser la copie?


@Neil, pouvez-vous élaborer? Spécifiquement, je ne pense pas que l'une ou l'autre condition énumérée à 12,8 / 15 s'applique à cette affaire. Il n'y a pas de déclaration de retour et il n'y a pas d'objet temporaire. En outre, considérez ideone.com/ajbr1 . Même avec g ++ -o4 , le constructeur de copie est appelé une fois par boucle. (Misté: oui, si le conteneur en question a une copie-constructeur sans effets secondaires, il peut être optimisé, pour 1,9 / 1 et 1,9 / 6. Mais je demande à propos d'un Constructeur de copie avec effets secondaires.)


@Rob, le compilateur peut optimiser tout ce qu'il peut prouver n'aura pas d'effet sur le résultat du programme. Donc, si vous créez, puis détruisez immédiatement un objet, alors en principe , le compilateur est absolument autorisé à optimiser le tout, à condition qu'il puisse prouver qu'il n'y a pas d'effets secondaires durables.


@bdonlan RVO est même autorisé lorsque le constructeur de copie a des effets secondaires majeurs (voir Stackoverflow.com/Questtions/4767620/... )


@bdonlan - Droite, et @stactedCooked - Droite. Mais je me demandais spécifiquement le cas où conteneur :: conteneur () a des effets secondaires. (Et RVO ne s'appliquent pas ici.)


@Rob, s'il a un effet secondaire visible, le compilateur doit conserver ces effets - mais pas sur IOTA plus. Heck, il pourrait (en principe) précalcompute tout ce que le constructeur de copie pourrait faire cela aurait des effets durables, puis simplement mettre un peu de code pour reproduire ces effets et rien d'autre.


3 Réponses :


3
votes

Pourquoi devrait-il? La meilleure solution consiste à utiliser le conteneur d'une certaine manière, comme en ajoutant sa taille à une variable globale.


2 commentaires

Il semble toujours probable que le compilateur puisse optimiser la copie ici. Voir mon édition pour un échantillon de code.


Oh, OK - Appelez ensuite une fonction sur la copie et l'original.



4
votes

Il est peu probable que la volatille effectue ce que vous attendez pour un type non de pod. Je recommanderais de passer un char * ou vide * aliasant le conteneur vers une fonction vide dans une unité de traduction différente. Étant donné que le compilateur n'est pas en mesure d'analyser l'utilisation du pointeur, cela agira en tant que barrière de mémoire compilateur, forçant au moins l'objet au cache du processeur et empêchant ainsi la plupart des optimisations d'élimination de la valeur morte.


0 commentaires

8
votes

La norme C ++ 03 indique que lit et écrit des données volatiles est un comportement observable (C ++ 2003, 1.9 [INTRO.EXECUTION] / 6). Je crois que cela garantit que l'affectation à des données volatiles ne peut pas être optimisée. Un autre type de comportement observable est des appels aux fonctions d'E / S. La norme C ++ 11 est encore plus sans ambiguïté à cet égard: 1,9 / 8 dit explicitement que

Le moins d'exigences sur une implémentation conforme sont:
- L'accès à des objets volatils est évalué strictement en fonction des règles de la machine abstraite.

Si un compilateur peut prouver qu'un code ne produit pas de comportement observable, il peut optimiser le code. Dans votre mise à jour (lorsque la volatilité n'est pas utilisée), le constructeur de copie et les autres appels de fonction et les opérateurs surchargés peuvent éviter tout appel d'E / S et accès à des données volatiles, et le compilateur pourrait bien comprendre. Toutefois, si gnumcopies est une variable globale utilisée ultérieurement dans une expression avec un comportement observable (E. G. imprimé), ce code ne sera pas supprimé.


0 commentaires