PERFORMANCE : I++ OU ++I ?

ndj55 Messages postés 13 Date d'inscription lundi 4 juin 2001 Statut Membre Dernière intervention 13 décembre 2002 - 3 nov. 2002 à 21:03
pasm Messages postés 3 Date d'inscription mercredi 14 septembre 2005 Statut Membre Dernière intervention 28 octobre 2006 - 23 oct. 2005 à 22:47
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/10095-performance-i-ou-i

pasm Messages postés 3 Date d'inscription mercredi 14 septembre 2005 Statut Membre Dernière intervention 28 octobre 2006
23 oct. 2005 à 22:47
Un détail trés important que vous avez tous oublié: le ++i incrémente i avant même de l'utiliser, alors que i++ fait de la post-incrémentation, en performance pure c'est identique. Il n'y a que la manière de la utiliser en fonction de l'optimisation des boucles que ça change...
Croqmort Messages postés 95 Date d'inscription mercredi 5 décembre 2001 Statut Membre Dernière intervention 27 juin 2006
12 janv. 2003 à 03:03
il ne faut pas oublier que le compilateur optimise le code, et transforme les i++ en ++i si ça s'avere utile.

le i++ requiert de creer une variable temporaire, car on peut faire tableau[i++]; et i va exister dans 2 etat un etat non incrementé temporaire pour l'indice du tableau, et un etat incrementer pour la nouvelle valeur de i.

il faudrai transformer en asm une class integer refaite avec post incrementation et pre incrementation et la transformer en asm, en desactivant si possible les optimisations.
JackosKing Messages postés 168 Date d'inscription mardi 31 décembre 2002 Statut Membre Dernière intervention 21 avril 2005
31 déc. 2002 à 15:20
heu... en asm 68k:
int *a=x;
b=*(++a); est beaucoup plus lente que b=*(a++);
equivalent a: (a= a0 b=d0 );
addq #1,a0
move.l (a0),d0
contre:
move.l (a0)+,d0
...
@+
PiXator Messages postés 16 Date d'inscription lundi 27 mai 2002 Statut Membre Dernière intervention 12 novembre 2004
21 nov. 2002 à 15:22
Et Ben !!!!!!!!!!!!!!!!!!!!!!!!
bleyblue Messages postés 3 Date d'inscription lundi 11 février 2002 Statut Membre Dernière intervention 19 novembre 2002
19 nov. 2002 à 18:11
Différence entre i++ et ++i :
Pour les opérations sur les types de données simples (int par exemple), la différence ne se situe pas dans l'opération elle - même (les codes asm sont équivalents) mais sur l'évaluation de l'expression. Je m'explique :
int i = 5;
( ++i == 5 ) est faux car l'incrémentation a lieu avant l'évaluation
int i = 5;
( i ++ == 5 ) est vrai car l'incrémentation a lieu après l'évaluation
J'espère que c'est clair...
cs_Lightness1024! Messages postés 162 Date d'inscription jeudi 15 mars 2001 Statut Membre Dernière intervention 1 avril 2005
10 nov. 2002 à 12:15
arf vous apportez de l'importance a cette difference ? sur des processeurs a 2 GHz perdre 3 cycles c pas un drame (OK si ya ke ca dans la boucle) mais en général un programme ca fait des milliers de lignes et mieux vaut se pencher sur les fonctions vraiment lentes style sqrt ou cos, sin, atn etc...
ndj55 Messages postés 13 Date d'inscription lundi 4 juin 2001 Statut Membre Dernière intervention 13 décembre 2002
9 nov. 2002 à 14:50
l'option /FA permet de générer un code asm intermédiaire...
il y a aussi /FC,qui génere un code COD...
Galett Messages postés 115 Date d'inscription jeudi 7 février 2002 Statut Membre Dernière intervention 21 mai 2005
9 nov. 2002 à 01:37
/FA ? ca fait quoi exactement ?
*va tester ça*
ndj55 Messages postés 13 Date d'inscription lundi 4 juin 2001 Statut Membre Dernière intervention 13 décembre 2002
8 nov. 2002 à 18:37
trinitacs-> Sous Visual Studio tu ajoutes l'option /FA pour le compilateur... Je ne sais pas pour GCC... Je t'assure que le code est le meme...

$L43572:
push esi
push OFFSET FLAT:??_C@_02JAFN@?$CFi?$AA@ ; `string'
call _printf
add esp, 8
inc esi
cmp esi, 32 ; 00000020H
jl SHORT $L43572

$L43576:
push esi
push OFFSET FLAT:??_C@_02JAFN@?$CFi?$AA@ ; `string'
call _printf
add esp, 8
inc esi
cmp esi, 32 ; 00000020H
jl SHORT $L43576

Voilà deux boucles qui font la meme chose mais l'incrmentation est différente... Tu vois bien que c'est la meme chose: "inc esi"...
trinitacs Messages postés 249 Date d'inscription mardi 16 juillet 2002 Statut Membre Dernière intervention 7 août 2003 2
8 nov. 2002 à 17:09
bdj55 >> Je ne suis pas d'accord pour dire que le code asm est le même pour ++i et i++. C'est vrai que d'après ce que tu nous montre on pourrait dire que c'est la même chose. Mais tu le sais bien comme tout le monde que i++ et ++i c'est différent donc le code source en asm ne peut pas être le même pour les deux.
Ou peut tu voir la sortie asm de ton compilo stplè?
ndj55 Messages postés 13 Date d'inscription lundi 4 juin 2001 Statut Membre Dernière intervention 13 décembre 2002
7 nov. 2002 à 21:45
trinitacs -> tu aurais du tout lire... regarde mon truc de code ASM... Le code ASM est le meme dans les deux boucles donc pas d'accélération ici...
Perso,j'utilise les deux,c'est selon mes humeurs...
Galett Messages postés 115 Date d'inscription jeudi 7 février 2002 Statut Membre Dernière intervention 21 mai 2005
6 nov. 2002 à 23:55
précompilation, voila le terme m'était sorti de la tête :)
merci Kinamstrong !
trinitacs Messages postés 249 Date d'inscription mardi 16 juillet 2002 Statut Membre Dernière intervention 7 août 2003 2
6 nov. 2002 à 14:53
Je confirme que ++i est plus raide que i++. Je n'ai pas tout lu car je n'ai pas le temps :( donc je risque de répéter ce que certains ont dit (enfin j'espère pas). Car quand on tape i++ une copie de i sera créé pour faire croire que i sera incrémenter après alors que ++i incrémente directement i. C'est comme si on sucharge l'opérateur ++ pour une classe. Si il est après la variable on renverra une copie de i à partir de la fonction operator++ ( int ); ( le int signale que c'est posincrémentation et rien pour une préincrémentation ).
Bon bref je vienx soutenir vieux lion car Jhep n'est pas complètement convaincu.
Sinon je répon à la question de vieux utlisez vous i++ ou ++i. J'utilise c++ car c'est plus jolie, sinon si la boucle est grande et la performance primordiale j'écris ++c .ourquoi c et non pas i comme tout le monde?? Par ce que c c'est le nom du langage et puis c c'est la premièere lettre de compteur :)

Sinon j'ai pas compris ton tableau?? i++ et ++i pour le int c'est kif kif mais pour les double ++i c'est 5 kilomèetre devant?

En tout cas merci vieux lion d'avoir mis une source avec les tests car je ne savais pas que la différence de temps était aussi grande pour les double.

Si après l'exemple de vieux lion il y a encore des gens qui pense que i++ et ++i sont aussi rapide je me tire une balle :(
ndj55 Messages postés 13 Date d'inscription lundi 4 juin 2001 Statut Membre Dernière intervention 13 décembre 2002
6 nov. 2002 à 13:16
euh dans le code ci dessus:
unsigned int ElapsedTime[NBR_THREADS]; es à remplacer par
unsigned int ElapsedTime[NBR_TESTS];
ndj55 Messages postés 13 Date d'inscription lundi 4 juin 2001 Statut Membre Dernière intervention 13 décembre 2002
6 nov. 2002 à 13:14
vieuxLion -> Une petite remarque... GetTickCount() est moi rapide que timeGetTime(). Si je peux me permettre,voilà un bon code de timer:

------------------------------------------------

#define NBR_TESTS 512 // Le Nombre De Mesures A Effectuer
ofstream StatFile;
int i;
unsigned long StartTime;
unsigned long EndTime;
unsigned int ElapsedTime[NBR_THREADS];
unsigned long TotalTime = 0;
float AverageTime;

for (i = 0; i < NBR_TESTS; ++i)
{
StartTime = timeGetTime();
/* C'est ici que doit se situer un appel unique à la fonction testée */
EndTime = timeGetTime();
ElapsedTime[i] = EndTime - StartTime;
}

StatFile.open("Stat.txt");

for (i = 0; i < NBR_TESTS; ++i)
{
StatFile << "Time For Thread " << i << " : " << ElapsedTime[i] << endl;
TotalTime += ElapsedTime[i];
}

StatFile << "---------------------------
Total Time: " << TotalTime << endl;
AverageTime = (float) TotalTime / (float) NBR_TESTS;
StatFile << "Average Time: " << AverageTime << endl;
StatFile.close();

-----------------------------------

Ici,un appel à la fonction entre les deux mesures de temps...
Dans un prog qui dessine des fractales,les écarts entre les fonctions identiques avec les meme arguments sont de l'ordre de 1 ou 2 millisecondes... Ce qui prouve que le timer est presque parfait,les différences de mesure pouvant etre dû aux aléas du systeme ou au manque de précision dans la mesure du temps...
Si quelqu'un veut bien refaire les tests de ce que dit vieuxLion avec cette méthode...
Sinon, si vous pensez que ce timer est encore imparfait... utilisez le Zen Timer de Michael Abrash écrit en ASM... Mais je pense qu'ici cé inutile...
ndj55 Messages postés 13 Date d'inscription lundi 4 juin 2001 Statut Membre Dernière intervention 13 décembre 2002
6 nov. 2002 à 13:04
Kinamstrong -> Je pense que l'on obtiendrait les memes résultats oui... En effet,quand le compilateur optimise,il prend en compte des cas particuliers... Additioner ou soustraire 1 est un cas particulier dans la mesure où il existe deux instructions destinées à ce genre d'opérations (inc et dec). C'est le meme principe que pour les multiplications/divisions par des entiers puissances de 2 (2,4,8,16...). En effet,si ton compilateur optimise correctement,il doit transformer i*=2 en i<<1 soit en ASM: shl ADRESS i,1 .
La différence majeure entre i++ et ++i réside en fait dans le fait que dans certains cas (fonction en général), la position de ++ (ou --) indique le moment où l'incrémentation doit être faite.... Ainsi,en notation préfixe cela signifie que l'on incrémente avant; en notation post-fixe,on incrémente après...
Kinamstrong Messages postés 42 Date d'inscription vendredi 11 janvier 2002 Statut Membre Dernière intervention 22 mai 2003
5 nov. 2002 à 17:59
i++ ou ++i ne serait pas comme des "alias" sous TUX ??????
des sortes de raccourcis de commandes.
Obtient-on les mêmes resultats avec i=i+1;

??????
Kinamstrong Messages postés 42 Date d'inscription vendredi 11 janvier 2002 Statut Membre Dernière intervention 22 mai 2003
5 nov. 2002 à 17:57
la discussion est de haut niveau et vous m'epatez !!!!!!
Mon prof me parlait d'une différence benine en tre les deux (++i et i++) mai la alors en faire un sujet c de la balle et franchement intéressant.
Au fait Galett , ta "macro compilation" ce n'est pas la précompilation!!!!!
@+
Galett Messages postés 115 Date d'inscription jeudi 7 février 2002 Statut Membre Dernière intervention 21 mai 2005
5 nov. 2002 à 14:05
il me semble, si qq1 peut confirmer, que pour le test de ndj55, il est normal que le code asm produit soit le même, car visual commence par des macros compilations (c'est surement pas le terme exact, mais ca devrait se rapprocher :)
Je m'explique, pour les 2 boucles qui sont différentes au niveau syntaxique, visual va faire une première passe pour essayer d'optimiser tout ça. Et ainsi il va transformé la seconde boucle en première boucle pour optimiser justement.
C'est comme si vous aviez sur une seule ligne :
i++;
j'espère bien que le compilateur va le traduire en ++i, sinon il serait pas très bon optimisateur, non ?


enfin c'est surtt une supposition, si qq1 pouvait le confirmer :)
Setaou Messages postés 127 Date d'inscription mercredi 28 mars 2001 Statut Membre Dernière intervention 4 octobre 2004
5 nov. 2002 à 09:34
il me semblait que pour un printf("%i", i++); i était affiché puis incrémenté, alors que pour printf("%i", ++i); il était incrémenté puis affiché ... Comment ca peut produire le même code ASM ?
cs_Xs Messages postés 368 Date d'inscription mercredi 14 novembre 2001 Statut Membre Dernière intervention 1 septembre 2008
4 nov. 2002 à 23:15
piouuuuuu !!!! alors, au final : c'est comme c'est demo de maths qui nous disent que 1 = 0 !
En clair, une erreur est quelque part, mais personne, ou du moin je crois, na la solutions.... donc pout moi ++i = i++ tjr. j'etais convaincu par le teste de jhep mais l'asm plus puissant et vrai lui donne tord.... ??!!
cs_vieuxLion Messages postés 455 Date d'inscription samedi 26 octobre 2002 Statut Membre Dernière intervention 6 avril 2004 8
4 nov. 2002 à 22:03
Merci tout le monde : le titre racolleur a marché... nombreux commentaires intéressants...
L'article (et mon bench) porte sur les structures et classes
En ce qui concerne les 'int' la variable temporaire est utilisée dans les deux cas car l'assembleur travaille déjà avec un Accumulateur et la zone mémoire.
C'est bien vu : il n'y a pas de différence... et le test de Jhep a plusieurs défauts :
1) il passe plus de temps à calculer time() que i++
2) le résultat n'est pas reproductible : inverser les deux tests pour voir !!!
3) il ne booste pas le process en real time pour être plus fiable : par ex :
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
pour Windows
mon Bench utilise GetTickCount() avant et après la boucle
cs_GoldenEye Messages postés 527 Date d'inscription vendredi 14 septembre 2001 Statut Membre Dernière intervention 6 octobre 2008 4
4 nov. 2002 à 20:42
Nan nan pas aussi hors sujet, j'ai rien dit. J'ai retesté ton truc ndj55 et je suis d'accord avec toi. Qui m'explique ? Vieuxlion, tu as fait ça avec quel compilateur ?
cs_GoldenEye Messages postés 527 Date d'inscription vendredi 14 septembre 2001 Statut Membre Dernière intervention 6 octobre 2008 4
4 nov. 2002 à 20:40
ndj55=> hors sujet je crois, il est question de surcharge de l'opérateur ++ d'après ce que j'ai compris. Ici ++i ou i++ est interprété de la même manière vu que i est un pauvre int. Par contre si c'est une structure plus évoluée, ça commence à changer des choses.
Je me contenterai de critiquer le titre un peu racoleur (faut bien que je justifie mon label de râleur invétéré !). pour le reste nickel
ndj55 Messages postés 13 Date d'inscription lundi 4 juin 2001 Statut Membre Dernière intervention 13 décembre 2002
4 nov. 2002 à 20:18
Je suis plus ou moins d'accord avec ta démonstration vieuxLion...
Regarde cela:
---------------------------------------------
for (i=0; i<32; ++i) // PreFix
printf("%i", i);

for (i=0; i<32; i++) // PreFix
printf("%i", i);
---------------------------------------------

regarde le code asm produit pas Visual Studio 6 avec optimisation:
---------------------------------------------
$L43572:
; Line 20
push esi
push OFFSET FLAT:??_C@_02JAFN@?$CFi?$AA@ ; `string'
call _printf
add esp, 8
inc esi
cmp esi, 32 ; 00000020H
jl SHORT $L43572
; Line 22
xor esi, esi
; Line 26
npad 7
$L43576:
; Line 23
push esi
push OFFSET FLAT:??_C@_02JAFN@?$CFi?$AA@ ; `string'
call _printf
add esp, 8
inc esi
cmp esi, 32 ; 00000020H
jl SHORT $L43576
---------------------------------------------

Et oui c'est exactement la meme chose pour les deux boucles... Donc pas de gain de perfs ici...
Galett Messages postés 115 Date d'inscription jeudi 7 février 2002 Statut Membre Dernière intervention 21 mai 2005
4 nov. 2002 à 00:16
juste un commentaire pour vieux lion, ça n'a rien à voir avec ton explication, c juste pour te féliciter des morceaux de code que tu laisses sur ce site, ca fait qqs semaines que tu en postes, ils sont très éducatifs, alors voila juste un clap clap !
sinon tu n'envisages pas de mettre toutes tes connaissances sur un site internet ?
ce serai très bénéfique pour de nombreux programmeurs je pense. :o)
cs_vieuxLion Messages postés 455 Date d'inscription samedi 26 octobre 2002 Statut Membre Dernière intervention 6 avril 2004 8
3 nov. 2002 à 23:26
merci du test Jhep
tu vois que l'on fait plus de boucles avec du ++i que du i++ ! (5%)

j'en profite pour joindre mon Benchmark dans la capture d'écran
elle indique 3% de gain pour une classe contenant un int, plus de 80% pour une classe contenant dix doubles et un int et 300% pour une classe contenant un char[256] et un int, etc...
cs_Jhep Messages postés 68 Date d'inscription dimanche 31 mars 2002 Statut Membre Dernière intervention 18 janvier 2010
3 nov. 2002 à 22:40
Démonstration un peu plus explicite :

#include <stdio.h>
#include <time.h>

void main()
{
time_t timer;
int s 0, i 0;
printf("Attendez 10 seconds SVP.
");
time(&timer);
s = timer;
while(timer - s < 10){
time(&timer);
i++;
}
printf("Resultat de la boucle avec i++ : %i
", i);

printf("Attendez 10 seconds SVP.
");
i = 0;
time(&timer);
s = timer;
while(timer - s < 10){
time(&timer);
++i;
}
printf("Resultat de la boucle avec ++i : %i
", i);
getchar();
}
cs_Jhep Messages postés 68 Date d'inscription dimanche 31 mars 2002 Statut Membre Dernière intervention 18 janvier 2010
3 nov. 2002 à 22:13
euh... tu peux répéter stp ?
ndj55 Messages postés 13 Date d'inscription lundi 4 juin 2001 Statut Membre Dernière intervention 13 décembre 2002
3 nov. 2002 à 21:03
Pas mal... Mais tu es sur de ce que tu dis?
Un ++i serait plus rapide qu'un i++ ?
Rejoignez-nous