Parcourir un vecteur - C++ - Programmation
Marsh Posté le 20-05-2005 à 18:35:38
for(vector<wxString>::size_type i=0;i<vect.size();i++){...}
la meilleur ? sur quel critère ?
Marsh Posté le 20-05-2005 à 18:44:49
Sur la vitesse à la quel le vecteur va être affiché...
Quel sera le code le plus rapide et pourquoi ?:
for(vector<wxString>::iterator i = vect.begin(); i != vect.end();++i){cout<<*i;}
for(int unsigned i=0;i<vect.size();i++){cout<<vect[i];}
Marsh Posté le 20-05-2005 à 18:57:08
fait le test avec un grand vector<int> et un traitement minimale dans la boucle. Moi je dirais que ca se vaut, mais meme si avec iterator c'est plus rapide ce n'est pas la le but ??
http://www.mindspring.com/~mgrand/ [...] m#Iterator
Marsh Posté le 20-05-2005 à 21:46:54
Y'en a un qui marche pour vector, un autre pour à peu près tous les conteneurs.
J'avais fait le test, le 2° était un peu plus rapide. Ca me parrait plutôt normal, mais à priori on peut pas généraliser pour tous les compilos / STL. Et puis c'est pas vraiment là que tu vas voir la différence. Ca devrait pas être ton critère n°1 de choix. J'utilise plus souvent le 2 pour les vector, car c'est plus court à écrire.
Marsh Posté le 20-05-2005 à 23:19:52
Je viens de faire le test et en fait, j'ai à peu près le même résultat pour les deux (g++ 4.0.0 sous windows).
Donc je choisirai le 1er qui a le mérite de pouvoir être facilement remplacé par un autre conteneur.
Marsh Posté le 21-05-2005 à 07:46:44
Franchement, je suis étonné que le 2 soit plus rapide, je m'attendrais à un résultat à peu de choses près identique, pour peu qu'on se donne la peine de déclarer l'itérateur correctement (et que l'implémentation de la STL soit optimisée). De toute façon, la 2e écriture n'est acceptable que pour les vecteurs. Pour les autres conteneurs, c'est jouer avec le feu.
Marsh Posté le 21-05-2005 à 10:53:40
Bon j'ai fait le test avec VC++ 2003 :
le 1er est clairement plus rapide.
Et voici les différents temps obtenus :
1er : for(vector<int>::iterator i = vect.begin(); i != vect.end();++i){*i = 1;}
avec optimisation :
g++ 4.0.0 : 3 secondes
VC++ 2003 : 3 secondes
sans optimisations :
g++ 4.0.0 : 14 secondes
VC++ 2003 : 21,1 secondes
2e : for(vector<int>::size_type i=0;i<vect.size();i++){vect[i] = 1;}
avec optimisation :
g++ 4.0.0 : 3 secondes
VC++ 2003 : 3 secondes
sans optimisations :
g++ 4.0.0 : 33,7 secondes
VC++ 2003 : 24,7 secondes
Marsh Posté le 21-05-2005 à 10:57:44
Tarabiscote a écrit : |
for(vector<wxString>::size_type i=0;i<vect.size();i++){...}
réitere plusieurs fois le test avec gcc pour avoir un temps plus precis
Marsh Posté le 21-05-2005 à 11:11:53
J'avais fait un copier coller dans mon message mais en fait c'était des int, je fais une affectation en plus, etc ...
Bon j'ai édité, sinon je suis désolé mais je l'ai lancé dans les 50 fois pour g++ et 2-3 fois pour VC++ 2003 à cause du temps qu'il met, mais le résultat est toujours le même.
PS : J'ai refais les tests en enlevant toutes les optimisations, je le rajoute avec les autres tests.
Marsh Posté le 21-05-2005 à 11:46:48
tu fais exactement les meme tests avec g++ et vs2003 ? si c'est le cas la difference est trop importante, tu devrais regarder la sortie asm de g++ avec optimisation pour voir ce qu'il fait réelement
Marsh Posté le 21-05-2005 à 12:05:57
J'affecte toujours des valeurs différentes et je fais afficher à la fin, je vois mal comment il ferait pour enlever des parties de codes si c'est ce que tu veux dire, sinon le code asm à l'air correct.
De plus si je double la boucle le temps est bien doublé.
PS : C'est exactement le même programme pour tous les tests.
Marsh Posté le 21-05-2005 à 12:13:49
alors comment ca pourrais etre 24 secondes avec vs et 3 secondes avec g++, c'est bien la meme machine ?
Marsh Posté le 21-05-2005 à 13:10:06
Ben g++ optimise bien
Tu peux faire des tests toi aussi, si t'as d'autres résultats...
Sinon on peut dire que, d'après mes résultats, le 1er est mieux (plus rapide, marche avec tous type de conteneurs), sauf avec les optimisations de g++ 4.0.0, dans ce cas les deux se valent (pour la vitesse).
PS : Oui, c'est bien la même machine.
Marsh Posté le 21-05-2005 à 13:30:23
mais ca donne quoi le code asm de la boucle comparer à vs2003 ?
Marsh Posté le 21-05-2005 à 14:42:34
Euh... A tout hasard, t'as laissé le mode debug de VS, fait toutes les contres-optimisation possibles pour lancer le troll nmake vs gcc 4 ?
Marsh Posté le 21-05-2005 à 14:46:58
IrmatDen a écrit : Euh... A tout hasard, t'as laissé le mode debug de VS, fait toutes les contres-optimisation possibles pour lancer le troll nmake vs gcc 4 ? |
C'est clair, j'allais dire la même chose
Marsh Posté le 21-05-2005 à 14:58:43
suffit de regarder l'assembleur ... la version avec iterator est un peu plus courte. Mais dans les 2 cas, la boucle principale est composée de 4 instructions sur ma machine. Donc les performances doivent être voisines
Marsh Posté le 21-05-2005 à 16:03:24
Taz a écrit : suffit de regarder l'assembleur ... la version avec iterator est un peu plus courte. Mais dans les 2 cas, la boucle principale est composée de 4 instructions sur ma machine. Donc les performances doivent être voisines |
Avec Visual Studio 2003, sur un exemple "real-life" en release multithreadé, on a ça qui est exécuté à chaque tour de boucle.
|
(les commentaires correspondent à ma compréhension du truc).
En gros, il teste si albums.begin() vaut NUL, et il compare ensuite la variable i (qui est sur la pile) à (end()-begin()/sizeof(void *)).
Bref, c'est pas dément. Mais d'un autre côté, l'aliasing est un gros problème des applis multi-threadées et VC++ est plutôt conservateur sur cet aspect là. Donc il est "obligé" de vérifier que le contenu du vecteur n'a pas été modifé entre-temps.
Je vais pas tarder à m'installer VC++2005 qui reconnait le mot __restrict (comme g++ 3.X d'ailleurs). On verra bien si ça permet de faire une différence. En attendant, il vaut mieux sortir le size() de la boucle car l'optimiseur ne le fait pas lui-même.
Marsh Posté le 21-05-2005 à 18:11:02
bref, je conclue : pour un parcours, iterator est vraiment meilleur parce que gcc (ça s'applique sans doute à d'autres compilateurs) incrémente son compteur de boucle 4 à 4 (la taille d'un int sur mon système), là ou a version size() fait un décalage de 2 (multplication par 4) après chaque incrémentation (étape inutile). Le code généré fait cependant la même taille.
Là où ça se complique, c'est lors d'un recopie
Code :
|
ici la version avec size() est nettement meilleur car, comme en C++, gcc produit un code qui n'utilise qu'une seul compteur, i. la version iterator est elle plus longue de 3 instructions car elle maintient 2 variable de boucle correspondant aux deux iterator.
Marsh Posté le 21-05-2005 à 18:23:36
fait gaffe au variable 3 et 4 dans le décallage de la dimension hexagonale tridimensionnelle.... t'embete aps installe acdsee version 7 je pense.
Marsh Posté le 21-05-2005 à 18:30:56
Hmmm, c'est là où on en vient à aimer le contrôle parental d'internet
Marsh Posté le 21-05-2005 à 18:36:04
Oups excuse moi je me suis trompé de topic..
Dans ton cas, utilise plutôt néro . et sinon fait un croisement des variables c et d du commun de la racine exponentielle du degé de la coupe de la varible du numéro du loto
Marsh Posté le 21-05-2005 à 18:40:00
ReplyMarsh Posté le 21-05-2005 à 22:44:04
Désolé je voulais juste montrer que le 1er code nest pas pire que le 2e.
Après je ne dis pas que dans certains cas avec certaines optimisations et certains compilateurs le 2e ne se comporte pas mieux.
En tout cas je ne voulais pas relancer la guerre entre VC et gcc.
J'utilise pas nmake, j'ai utilisé ça comme option (j'utilise pas trop VC++ donc y a sans doute mieux) : /D "NDEBUG" /G7 /arch:SSE2 /link /OPT:NOWIN98
Sinon j'ai même pas mis toutes les options de g++ ...
Enfin l'avantage de VC++ ça reste la taille de l'exe (88ko contre 533ko).
Marsh Posté le 21-05-2005 à 22:46:07
n'importe quoi ... c'est pas parce que tu sais pas te servir de g++ qu'il faut tirer des conclusions hatives
Marsh Posté le 21-05-2005 à 22:49:43
Quelles conclusions hâtives ?
Je suis le seul a avoir un temps sois peu montré des résultats, j'ai jamais empêcher personne de poster d'autres résultats et d'en tirer d'autres conclusions.
Alors j'espèrerai un peu plus de bonne fois.
Marsh Posté le 21-05-2005 à 23:19:02
Tarabiscote a écrit : |
ça par exemple.
Marsh Posté le 21-05-2005 à 23:22:12
Sans doute parce qu'il oublie de préciser qu'il faut 15 meg de DLL pour que ça tourne
Marsh Posté le 21-05-2005 à 23:32:07
Friday Monday a écrit : Sans doute parce qu'il oublie de préciser qu'il faut 15 meg de DLL pour que ça tourne |
Mouais enfin
VC++ 2003 : kernel32.dll
gcc 4.0.0 : kernel32.dll plus msvcrt.dll
C'est pas vraiment ce que j'appele 15mo de plus ...
En tout cas c'est pas en faveur de gcc tout ça ...
Marsh Posté le 21-05-2005 à 23:39:38
je comprends rien à vos histoires : la taille du binaire gcc ou VS est grosso modo là même
Marsh Posté le 21-05-2005 à 23:45:45
Non car moi je compile pour mingw32, si tu compiles pour cygwin ou linux, dans ce cas là peut-être.
Mais quand on est sous windows c'est quand même mieux de ne pas avoir à passer par cygwin, enfin moi je préfère mais ce nest quune question de goût.
Marsh Posté le 21-05-2005 à 23:58:21
si tu compiles correctement avec mingw, tu obtiens une taille de binaire comme VS.
Marsh Posté le 22-05-2005 à 01:39:32
Tarabiscote a écrit : J'utilise pas nmake, j'ai utilisé ça comme option (j'utilise pas trop VC++ donc y a sans doute mieux) : /D "NDEBUG" /G7 /arch:SSE2 /link /OPT:NOWIN98 |
Et avec "/O2" (opt. for speed) ou "/O1" (opt. for size), ça donne quoi ?
Marsh Posté le 22-05-2005 à 09:34:38
Ah ben voilà, je suis bête j'avais oublié de mettre /O2. (j'avais mis /03 comme sur gcc mais ça faisait rien alors je l'avais enlevé mais en fait c'était /02 )
Donc c'est bon on a bien 3 secondes pareil
PS : Taz, ça m'intéresserai bien de savoir comment tu fais pour la taille.
Edit : Revenons au sujet voici la différence entre les deux :
1er
L65: |
2e
L37: |
Donc avec optimisation, je ne vois pas de différence du moins dans la boucle (y a plus qua vérifier le nombre de cycles par instructions pour être vraiment complet).
Je vais essayé de regarder un peu l'initialisation aussi mais la différence est négligeable (s'il y en a une).
Marsh Posté le 20-05-2005 à 18:10:15
Bonjour,
J'ai trouvé 2 façons de parcourir un vecteur:
for(vector<wxString>::iterator i = vect.begin(); i != vect.end();++i){...}
for(int unsigned i=0;i<vect.size();i++){...}
Quel façon est la meilleur et pourquoi ? merci...