9
votes

Pourquoi différer (! =, <>) Est plus rapide que égal (=, ==)?

J'ai vu des commentaires sur ce que " <> est plus rapide que = " ou "! = plus vite que = = "dans un si () instruction.

J'aimerais savoir pourquoi est-ce le cas. Pourriez-vous montrer un exemple dans ASM?

Merci! :)

EDIT:

Source

Voici ce qu'il a fait. xxx


8 commentaires

Veuillez fournir un lien vers l'un de ces commentaires.


Spéculation pure, à moi


Stackoverflow.com/Questtions/1105519/... Vérifiez le code


@John Si c'est vrai, et il n'y a aucune preuve dans le code que c'est, c'est un bogue dans le compilateur Delphi. La comparaison de deux octets est typiquement la même instruction de la machine, que vous soyez ensuite sur l'égalité ou l'inégalité.


Cette question reste inconnue pour le moment. Je suis avéillé quiconque qui a essayé de le prouver le trual ou le vrai. J'apprécie les réponses que vous m'avez données et que je ne regrette pas que je me demandais ici. :)


Pourquoi ne demandez-vous pas de demander à l'auteur de ces mots?


Réponse courte: Certains processeurs ont le foo! = Null A.K.A. FOO! = 0 Comparaison optimisée.


J'ai entendu le moins de temps qu'un processeur est devenu plus rapide, il devient quelque chose à faire avec des électrons devenant en forme.


12 Réponses :


19
votes

J'aurais prétendre que cela est à plat tort, sauf peut-être dans des circonstances très spéciales. Les compilateurs peuvent refroidir un dans l'autre sans effort (en activant simplement le si et sinon cas).


0 commentaires

1
votes

Si vous pouvez fournir un petit exemple qui montre clairement une différence, je suis sûr que la communauté de dépassement de la pile pourrait expliquer pourquoi. Cependant, je pense que vous pourriez avoir des difficultés à construire un exemple clair. Je ne pense pas qu'il y aura une différence de performance notable à une échelle raisonnable.


4 commentaires

Je suis désolé, vous pouvez le voir maintenant.


Ce n'est pas un exemple que je peux compiler et courir (même si j'avais Delphi).


@ Greg, sa seule ligne seulement. Si (0xFF! = 255) retour; ou si (256 = $ fe) retour;


Oui, je vois ça, mais je ne vois pas la preuve qu'il y a une différence du tout.



1
votes

Je doute fortement qu'il y ait une différence de vitesse. Pour des types intégrés, par exemple, vous obtenez une instruction CMP et que JZ (saut si zéro) ou Jnz (saut si pas zéro), selon que vous utilisiez = ou ≠. Il n'y a pas de différence de vitesse ici et je m'attendrais à ce que cela soit aussi vrai à des niveaux plus élevés.


0 commentaires

4
votes

spontané cependant; La plupart des autres choses de votre code affecteront les performances plus que le choix entre == et! = (ou = et <> en fonction de la langue).

Lorsque j'ai dirigé un test en C # sur plus de 1000000 itérations de chaînes comparatives (contenant l'alphabet, A-Z, avec les deux dernières lettres inversées dans l'une d'entre elles), la différence était comprise entre 0 et p>

Il a été dit avant: écrivez le code de lisibilité; Changement en code plus performant quand il a été établi qu'il faudra une différence .

Modifier: répété le même test avec des tableaux d'octets; même chose; La différence de performance est négligeable.


0 commentaires

2
votes

Je prétendrais que c'était un faux arrêt à plat. Le test d'égalité est toujours le même que le test d'inégalité. Avec une chaîne (ou des tests de structure complexes), vous allez toujours casser exactement le même point. Jusqu'à ce que ce point de rupture soit atteint, la réponse à l'égalité est inconnue.


0 commentaires

5
votes

Pour .NET Langues

Si vous regardez l'IL du string.op_equality et string.op_inequalité Méthodes, vous verrez que les deux internall appellent String.equals.

mais le op_inequalité invertit le résultat. Ceci est deux déclarations IL plus.

Je dirais que la performance est la même, avec peut-être une petite performance (très petite, très très petite) pour la déclaration ==. Mais je crois que le compilateur Optimizer & Jit supprimera ceci.


2 commentaires

Votre dernière phrase est importante: ce que vous avez vu dans IL peut n'avoir aucune incidence sur le code éventuellement exécuté.


Mais il faudra 2 déclarations il plus à JIT (ou pré-jit, et optimiser) 4 octets plus à charger, etc. Si vous mettez cela ensemble ... ;-)



1
votes

Cette liste (en supposant qu'il est sur X86) des instructions de l'ASM pourrait aider:

  • Sauter si plus grand
  • Sauter sur l'égalité
  • comparaison entre deux registres

    (non-responsabilité, je n'ai rien de plus que l'expérience très basique avec l'assembleur d'écriture afin que je puisse être hors de la marque)

    Cependant, cela dépend évidemment des instructions de montage du compilateur Delphes. Sans voir cette sortie, il s'agit de devinettes. Je vais garder ma citation de Donald Knuth en tant que responsable de ce genre de chose pour tous, sauf un jeu d'applications de niche (jeux, appareils mobiles, applications de serveur haute performance, logiciels de sécurité, lance-missiles, etc.) est la chose que vous s'inquiéter de la dernière fois à mon avis.

    "Nous devrions oublier petit Généralités, disons environ 97% de la TEMPS: L'optimisation prématurée est la racine de tout mal. "

    Si vous écrivez un de ceux-ci ou similaire, alors évidemment, vous vous souciez, mais vous ne l'avez pas spécifié.


2 commentaires

Qu'est-ce que cela a à voir avec la question? Si un opérateur était plus rapide que l'autre, cela serait essentiel de savoir à cause des implications pour l'architecture et comment nous devrions écrire du code. Même une telle micro-optimisation serait utile si elle était appliquée de manière cohérente.


Votre réponse contredit votre commentaire



1
votes

Eh bien, cela pourrait être ou ça ne pouvait pas être, c'est la question suivante :-) La chose est que cela dépend de la langue de programmation que vous utilisez. Étant donné que toutes vos déclarations finiront par finir par des instructions à la CPU, celle qui utilise le moins d'instructions pour atteindre le résultat sera la plus rapide.

Par exemple, si vous dites que les bits x sont égaux aux bits y, vous pouvez utiliser l'instruction qui utilise un xor utilisant les deux bits comme une entrée, si le résultat est autre que 0, il n'est pas le même. Alors, comment sauriez-vous que le résultat est autre que 0? En utilisant l'instruction qui retourne true si vous dites que l'entrée A est supérieure à 0.

C'est déjà 2 instructions que vous utilisez pour le faire, mais comme la plupart des CPU ont une instruction qui se compare en un seul cycle, il s'agit d'un mauvais exemple.

Le point que je fais est toujours le même, vous ne pouvez pas faire ces déclarations généralement sans fournir le langage de programmation et l'architecture de la CPU.


0 commentaires

6
votes

Cela pourrait avoir quelque chose à voir avec la prédiction des succursales sur la CPU. La prédiction des succursales statiques prédirait qu'une succursale ne serait tout simplement pas prise et récupérerait la prochaine instruction. Cependant, presque personne ne l'utilise plus. Autre que cela, je dirais que c'est taureau parce que les comparaisons doivent être identiques.


0 commentaires

1
votes

Juste deviner, mais vous souhaitez conserver la logique, vous ne pouvez pas simplement remplacer xxx

avec xxx

pour conserver la logique , le code d'origine doit avoir été quelque chose comme xxx

ou xxx

et qui peut vraiment être un peu plus lentement que le test sur l'inégalité.


2 commentaires

Les deux sont cmp suivis d'une branche. Je ou jne. Et presque tous les processeurs ont un drapeau zéro et des moyens de le tester.


Il peut être optimisé par le compilateur, mais "non (a = b)" semble être un peu plus de travail que "A <> B". Bien que le premier est un comparateur suivi d'une négation, le second est un comparateur seulement. Je ne suis pas sûr de la version "sinon", cependant.



4
votes

Cela pourrait également résulter d'une interprétation erronée d'une expérience.

La plupart des compilateurs / optimiseurs supposent qu'une succursale est prise par défaut. Si vous inverser l'opérateur et l'ordre IF-alors-alors, et la succursale qui est maintenant prise est la clause de l'autre, cela pourrait provoquer un effet de vitesse supplémentaire dans le calcul hautement en calcul (*)

(*) Évidemment, vous devez faire beaucoup d'opérations pour cela. Mais cela peut être important pour les boucles les plus strictes par ex. codecs ou analyse d'image / vision de la machine où vous avez 50 Mo / s de données au chalut. .... Et puis je ne sois même que sur ce niveau pour le code vraiment réutilisable. Pour le code d'entreprise ordinaire, cela ne vaut pas la peine.


0 commentaires

6
votes

Je pense qu'il y a une certaine confusion dans votre question précédente sur ce que l'algorithme était que vous essayiez de mettre en œuvre, et donc dans ce que le" spef-up "prétendait faire.

Voici un démontage de Delphi 2007. Optimisation sur. (Remarque, Optimisation a changé le code un peu, mais pas de manière pertinente. P>

Unit70.pas.31: for I := 0 to 100 do
004552B5 33C0             xor eax,eax
Unit70.pas.33: if i = j then
004552B7 3B02             cmp eax,[edx]
004552B9 7506             jnz $004552c1
Unit70.pas.34: k := k+1;
004552BB FF05D0DC4500     inc dword ptr [$0045dcd0]
Unit70.pas.35: if i <> j then
004552C1 3B02             cmp eax,[edx]
004552C3 7406             jz $004552cb
Unit70.pas.36: l := l + 1;
004552C5 FF05D4DC4500     inc dword ptr [$0045dcd4]
Unit70.pas.37: end;
004552CB 40               inc eax
Unit70.pas.31: for I := 0 to 100 do
004552CC 83F865           cmp eax,$65
004552CF 75E6             jnz $004552b7
Unit70.pas.38: end;
004552D1 C3               ret 


0 commentaires