En testant mon code, j'ai remarqué une augmentation significative du temps d'exécution lorsque le rang vide- for loop
a été supprimé ou non. Normalement, j'aurais pensé que le compilateur aurait remarqué que la boucle for ne sert à rien et qu'elle serait donc ignorée. Comme les drapeaux du compilateur que j'utilise -O3
( gcc 5.4
). Je l'ai également testé avec un vecteur au lieu d'un ensemble et cela semble fonctionner et donner le même temps d'exécution dans les deux cas. Il semble que l'incrémentation de l'itérateur coûte tout le temps supplémentaire.
Premier cas avec la boucle for rangée toujours présente (lente) :
#include <iostream>
#include <set>
int main () {
long result;
std::set<double> results;
for (int i = 2; i <= 10000; ++i) {
results.insert(i);
for (auto element : results) {
// no operation
}
}
std::cout << "Result: " << result << "\n";
}
Deuxième cas avec la boucle for rangée supprimée (rapide) :
#include <iostream>
#include <set>
int main () {
long result;
std::set<double> results;
for (int i = 2; i <= 10000; ++i) {
results.insert(i);
}
std::cout << "Result: " << result << "\n";
}
3 votes
Dans certains cas
-O3
pourrait en fait être pire que-O2
. Essayez d'utiliser-O2
et jetez également un coup d'œil au code généré.2 votes
En regardant cela dans godbolt Il semble que le compilateur n'optimise pas les incréments de std::set::iterator (c'est-à-dire que ce problème est également présent lors de l'utilisation d'une boucle for "normale" utilisant des itérateurs). Je ne sais pas pourquoi le compilateur n'optimise pas cette boucle.
4 votes
Après avoir regardé le désassemblage, je confirme que ni gcc, ni clang, ni VS ne l'optimisent avec O2, O3 ou Os.
0 votes
-L'oxygène ne semble pas faire de différence
0 votes
@YSC une boucle vide est une boucle vide. Ce n'est pas minimal quand le vrai problème ne contient pas de boucle vide. Et si c'est le cas, c'est de la merde.
1 votes
@manni66 Une vraie connerie est que cette situation peut se produire dans du code de production et que le compilateur ne l'optimisera pas.
0 votes
Il semble que le problème apparaisse lorsque l'on boucle sur une liste :
void f (const std::list<double>& l) { for (auto e : l) {}}
6 votes
Constatez-vous le même effet avec d'autres conteneurs (notamment
std::array
) ? Si ce n'est pas le cas, il est probable que les itérateurs de l'ensemble sont trop complexes pour l'optimiseur.7 votes
@manni66 et celui qui pense que tout le code de production est écrit à la main devrait ralentir son jugement....
1 votes
Il semble que std::array soit optimisé, mais que std::vector ne le soit pas ; ce qui me fait penser que @TobySpeight a touché la cible, ou qu'il y a un effet secondaire des itérateurs que le compilateur ne se sent pas en sécurité de supprimer.
1 votes
Il semble que tout type de traversée basée sur les nœuds empêchera l'optimisation, même sur le type de liste le plus simple. Voici un exemple avec une liste singulièrement liée minimale et roulée à la main .
0 votes
Avec
std::vector
gcc-7.2 en-O2
n'optimise pas l'itération : godbolt.org/g/aKNbkx0 votes
Les compilateurs ne semblent pas optimiser cela :
struct S { S* next; };
void f (S* s) { while (s) s = s->next; }
Je ne sais pas pourquoi.2 votes
@ComicSansMS Il semble que ce soit seulement le cas pour gcc et clang. icc18 optimise la boucle vide.
0 votes
Je dirais que la raison pour laquelle ce n'est pas optimisé, c'est que la boucle ne devrait pas être là en premier lieu. Il n'est pas courant qu'un code boucle sur quelque chose sans effectuer de travail. Vous ne pouvez donc pas vous attendre à ce que les auteurs du compilateur aient inclus des optimisations pour ce seul code. J'en suis venu depuis longtemps à la conclusion que ce genre de problèmes surgira toujours si vous comptez sur votre optimiseur pour faire le ménage derrière vous. Écrivez un code propre qui fait un travail raisonnable, et votre optimiseur sera votre ami ; écrivez un code gonflé, et votre optimiseur vous laissera tomber là où vous en avez le plus besoin.
0 votes
Comment voulez-vous que le compilateur sache que l'itérateur de la collection n'a pas d'effets secondaires dont vous avez l'intention de tirer parti ?