IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

i++ vs i=i+1


Sujet :

C#

  1. #1
    Membre à l'essai
    Inscrit en
    Juillet 2005
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 26
    Points : 19
    Points
    19
    Par défaut i++ vs i=i+1
    Hello!

    En C++, il est recommandé de faire i++; au lieu de i=i+1, quand on fait du calcul numerique, pour des raisons de performance.

    Je me demandais si cela etait egalement vrai en c#, ou s'il n'y a pas de difference entre les deux facons d'incrementer niveau perf ?

    Merci

  2. #2
    Rédacteur

    Inscrit en
    Juin 2004
    Messages
    744
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Juin 2004
    Messages : 744
    Points : 1 352
    Points
    1 352
    Par défaut
    Je ne pense qu'il y ai de grandes différences ....

    Si tu fais un programme gérant la synchronisation d'allumage de moteurs de fusée peut être .... Mais dans la pluparts des développement ça n'a aucune importance

    De plus je pense que le i++ n'éxiste pas en vb.net donc ça voudrait dire que le framework .net n'en tient pas réellement compte.

    Ludovic,

  3. #3
    Membre à l'essai
    Inscrit en
    Juillet 2005
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 26
    Points : 19
    Points
    19
    Par défaut
    Sur du calcul numerique (manipulation de grosses matrices, enormement de boucles imbriquées, des milliards d'incrementations a faire), il y a bien une difference de perf en c++ qui est visible entre utiliser i++ ou i=i+1 . (que j'avais pu benchmarquer il y a quelque temps)
    En fait, si je me souviens bien, i++ permet de ne stocker la variable i que dans un seul registre, alors que i = i + 1 necessite 2 registres (car copie temporaire de i+1 dans un autre registre)


    Je n'ai pas fait de benchmark en c# (et je suis debutant en c# donc je me demandais si ca valait meme le coup de faire le bench, si qqun confirme que le framework ignore l'incrementation de la facon ++).

    Des experts se sont deja posé la question ?

  4. #4
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Points : 1 561
    Points
    1 561
    Par défaut
    en réalité ce n'est pas qu'une question de stockage dans un registre

    i++ charge i dans un registre, puis une instruction native effectue une incrémentation, puis on stocke la valeur du registre dans i

    i = i + 1 charge i dans un registre, 1 dans un second registre et on effectue une addition des deux registres dans le premier puis on stocke la valeur ainsi obtenue dans i.

    les deux grosses différences ici sont les suivantes :

    - chargement d'une valeur dans un second registre au lieu d'un seul.
    - utilisation de l'instruction inc dans le premier cas, et de l'instruction add dans le second.

    là où le gain de performance est le plus significatif c'est dans le deux types d'instruction exécutées sur le processeur.
    En effet, une incrémentation est une instruction "cablée" qui prend de 1 à 3 cycles horloge sur le processeur.
    L'addition elle est une instruction "micocontrollée" qui prend de 8 à 15 cycles pour s'exécuter sur le processeur. Car il faut traiter deux registres, puis modifier un registre...

    De plus l'unité arithmétique n'est pas appelée de la meme facon selon que l'on fait une incrémentation ou décrémentation, pour des questions de performances, lorsque l'on incrémente de 1 ou décrémente de 1 d'ailleurs, il est facile de prédire et prévoir le comportement de la retenue propagée d'un bit à l'autre, ce qui fait qu'on ne la propage pas directement dans le calcul, on calcul donc chaque bit séparément et parallelement, alors que dans une addition, où a priori on ne connait pas la valeur contenue dans le second registre, on ne peut pas faire de prédiction ni connaitre à l'avance la réaction de la retenue, ce qui nous oblige à effectuer la propager dans le calcul de chaque bit, ce qui nous oblige à serialiser le calcul de chaque bit.

    Ah oui autre considération qui n'arrange rien, en code machine, une incrémentation se résume par une commande de 1 à 4 octets, alors que pour l'addition, ca se gatte... on a d'abord une instruction de 1 à 4 octets, puis une valeur sur 4 ou 8 octets selon que l'on fait un calcul en 8/16/32 bits ou sur 64 bits.
    Les temps de chargement ne sont pas les memes non plus car les mécanisme dans le processeur ne sont pas les memes. C'est également une des raisons à cette différence, dans les cycles horloges consommés.

    Il est a noté toutefois que cette différence est suceptible de s'estomper sur les processeurs RISC dans la mesure ou les jeux d'instructions sont plus réduits, ensuite le fait de conserver INC au profit de ADD est à la discretion des concepteurs, mais tant que les deux instructions coexistes au sein d'un meme processeur, il continuera de subsister des différences entre i++ et i=i+1.

    Ensuite il y a l'aspect Framework, en réalité n'ayant jamais chercher à approfondir en apprenant le MSIL, j'ignore si il existe deux instructions IL différentes et si oui, si elles sont utilisées lors de la compilation.
    Ensuite dans la mesure où microsoft n'est pas locace sur le code natif généré par le CLR pour exécuter plus rapidement le code managé, j'ignore totalement si microsoft tire partie et avantage de cette différence d'architecture pourtant présente sur à peu près tous les processeurs du marché.
    En gros soit il existe une commande i++ et ca compile en inc i, soit il n'en existe pas et sa compile toujours en i = i + 1 ou sa n'existe pas mais leur compilateur est super optimisé et remarque ce pattern et génere en i++.

    Il faudrait faire des tests pour pouvoir en être sure.
    Car même si .NET a pour but d'uniformiser les langage, le fait qu'une construction n'existe pas dans un langage ne signifie pas pour autant que les autres langages ayant cette construction n'en tire pas profit. Car il y a là aussi une différence de performance.
    A savoir que VB est un des rares langages .NET à ne pas différencier l'incrémentation par une instruction spécifique.

  5. #5
    Rédacteur

    Inscrit en
    Juin 2004
    Messages
    744
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Juin 2004
    Messages : 744
    Points : 1 352
    Points
    1 352
    Par défaut
    Si tu fais un benchmark entre les deux méthodes, poste le résultat sur ce forum ça peut être sympa

    Merci

  6. #6
    Membre à l'essai
    Inscrit en
    Juillet 2005
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 26
    Points : 19
    Points
    19
    Par défaut
    Merci cinemania pour ces explications
    Des que j'ai un peu de temps je vais essayer de faire le bench pour voir.

  7. #7
    Membre confirmé
    Inscrit en
    Juin 2007
    Messages
    459
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 459
    Points : 553
    Points
    553
    Par défaut
    Je peux répondre sur un point :
    les deux instructions C#
    conduisent à la génération des mêmes instructions MSIL add.

    Reste à savoir ce qu'il se passe pour la génération de code natif.

  8. #8
    Rédacteur

    Inscrit en
    Juin 2004
    Messages
    744
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Juin 2004
    Messages : 744
    Points : 1 352
    Points
    1 352
    Par défaut
    Je pense aussi que le framework interprete de la meme manière :

    i++
    i+=1
    i = i + 1

    Mais ça reste à prouver

  9. #9
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Points : 1 561
    Points
    1 561
    Par défaut
    des 3 écritures suivantes :

    i++;
    i = i + 1;
    i += 1;

    la plus belle reste encore i++;

    ah autre notion amusante il existe une instruction ++i;

    en réalité il y a une bonne raison à l'existance de i++ et de ++i comparé à i = i + 1;

    lorsque l'on fait a[i++];

    il charge la valeur de a[i] puis effectue i += 1;
    alors que si tu fait a[++i] il fait d'abord i += 1 et charge ensuite a[i];

    ce qui bien sure ne signifie plus la meme chose

    donc techniquement c'est le meme code, mais l'ordre de précédence et de priorité des opérateurs et opérations arithmétique n'est pas du tout le meme.

  10. #10
    Membre à l'essai
    Inscrit en
    Juillet 2005
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 26
    Points : 19
    Points
    19
    Par défaut
    bon effectivement, en regardant avec ildasm on obtient le meme code genere, que l'on utilise :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    i++;
    i=i+1;
    i+=1;
    à savoir sur un int :

    Si on fait i=i+x, on obtient



    Donc sauf erreur, il ne sert a rien de faire i++ au lieu de i=i+1 comme en c++.
    Ca voudrait dire qu'en .net sur du calcul numerique on ne pourrait pas benificier du petit gain en perf permis par le c++ sur une incrementation, c'est un petit peu decevant

  11. #11
    Expert confirmé
    Avatar de ced600
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Août 2006
    Messages
    3 364
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Août 2006
    Messages : 3 364
    Points : 4 061
    Points
    4 061
    Par défaut
    des 3 écritures suivantes :

    i++;
    i = i + 1;
    i += 1;

    la plus belle reste encore i++;

    ah autre notion amusante il existe une instruction ++i;

    en réalité il y a une bonne raison à l'existance de i++ et de ++i comparé à i = i + 1;

    lorsque l'on fait a[i++];

    il charge la valeur de a[i] puis effectue i += 1;
    alors que si tu fait a[++i] il fait d'abord i += 1 et charge ensuite a[i];

    ce qui bien sure ne signifie plus la meme chose

    donc techniquement c'est le meme code, mais l'ordre de précédence et de priorité des opérateurs et opérations arithmétique n'est pas du tout le meme.
    C'est vrais en c++. Mais as tu déjà essayé en C# ?

  12. #12
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Juin 2005
    Messages
    288
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2005
    Messages : 288
    Points : 375
    Points
    375
    Par défaut
    C'est vrai aussi en C#

  13. #13
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    652
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 652
    Points : 730
    Points
    730
    Par défaut
    Citation Envoyé par ppaul127
    En C++, il est recommandé de faire i++; au lieu de i=i+1, quand on fait du calcul numerique, pour des raisons de performance.
    Pour des raisons de perfs, il est recommandé de faire ++i au lieu de i++ d'ailleurs (en C++ toujours)

    En C#, i++ est juste plus simple/joli/pratique à taper. Ça reste un avantage suffisant pour justifier d'utiliser ça au lieu de i += 1 ou (pire) i = i + 1 (qui ne devrait jamais être utilisé quelque soit l'incrément, sinon l'opérateur += risque de se mettre en grève)

    Bref, ++i forever (ou i++ pour les moins habitués :)

  14. #14
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Points : 1 561
    Points
    1 561
    Par défaut
    effectivement, en .NET visiblement il n'y a pas d'avantage kk soit l'écriture.. cependant qui nous dit que la CLR n'est pas bien faite et repère les incréments pour les transformer en INC processeur plutot qu'un ADD...

    Après tout certains compilateurs comme gcc dans certains cas convertisse une écriture i=i +1 en i++ de par eux meme si certaines options sont activées.

  15. #15
    Membre actif
    Profil pro
    Inscrit en
    Février 2005
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2005
    Messages : 56
    Points : 219
    Points
    219
    Par défaut
    Pour des raisons de perfs, il est recommandé de faire ++i au lieu de i++ d'ailleurs (en C++ toujours)
    C'est ce que j'ai très récemment lu qquepart, en fait il était dit que ++i ne pouvait jamais être pire que i++.
    Mais pourquoi?

  16. #16
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Points : 1 561
    Points
    1 561
    Par défaut
    Petit cours de processeur encore et toujours...

    En fait i++ et ++i sont deux instructions différentes...
    mais ++i est prioritaire, mais i++ est un des opérateurs les moins prioritaire qui soit... C'est également vrai lors d'écriture de code en assembleur.
    En plus le code généré sera différent dans le cas d'un ++i a un i++.

    Et comme si ce n'était pas tout, pour des raisons d'architecture à la con, i++ prend un cycle de plus que ++i au niveau du processeur... c'est relatif aux chargements dans l'unités arithmétique et dans l'ordre des traitements.
    (Toutefois cette notion en terme de processeur n'est pas systematiquement valide, cela dépend du processeur...)

    mais comme dans tous les cas ++i est prioritaire, il sera écrit très différemment en code machine et économisera pas mal de code.

  17. #17
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    652
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 652
    Points : 730
    Points
    730
    Par défaut
    Wai bon, version simple :

    ++i incrémente i puis retourne la valeur de i (incrémenté)
    i++ fait une copie de i, incrémente i puis retourne la valeur copiée (avant incrémentation)

    Donc i++ est plus lent (en C/C++) parce que causant une copie supplémentaire. Rien de plus.

    C'est pas une question de priorité ou d'architecture. Juste une question de fonctionnement.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo