Question

Avertissement:Je ne suis pas un compilateur expert.Je suis tout simplement curieux et viennent chercher de l'illumination.

J'ai vu des gens prétendent que -- pour l'efficacité -- for les boucles doivent généralement utiliser un zéro de comparaison pour la résiliation.Donc, plutôt que de:

void blink1(int n) {
    for (int i=0; i<n; i++) {
        blink_led();
    }
}

vous devez écrire:

void blink2(int n) {
    for (int i=n; i>0; i--) {
        blink_led();
    }
}

Je pensais que c'était un peu idiot:pourquoi mettre le fardeau sur l'humain, si un compilateur pourrait interpréter à la fois des cas "blink_led() n fois"?

Mais à l'aide de M.Godbolt du Compilateur Explorer, Maintenant je pense que je me trompe.Pour tous les compilateurs j'ai essayé, le "comparer à zéro", toujours produit une boucle plus courte.Par exemple, x86-64 ccag 10.2 avec-O3 optimisation produite l'intérieur des boucles:

blink1:
    ...
.L3:
        xor     eax, eax
        add     ebx, 1
        call    blink_led
        cmp     ebp, ebx
        jne     .L3

vs

blink2:
    ...
.L12:
        xor     eax, eax
        call    blink_led
        sub     ebx, 1
        jne     .L12

Alors, voici la question

Ce semble un cas courant.

Pourquoi ne peut pas (ou pourquoi ne pas) le compilateur avis que l'effet de la for la boucle est tout simplement "faire cette chose N fois" -- si le comptage ou le compte à rebours -- et optimiser pour qui?

Était-ce utile?

La solution

Ce que vous lisez est un non-sens total, sauf pour les plus primitifs de compilateurs.Tout d'abord, la comparaison avec un entier est aussi rapide, voire plus rapide que la comparaison avec une constante.Deuxièmement, une bonne optimisation du compilateur prendra une boucle écrite à l'aide de certains modèle commun et de le transformer en le meilleur code possible;il peut ne pas reconnaître votre obscurci modèle et produire moins bon code.

Et enfin, vous ne devriez pas remplacer lisible avec le code illisible, sauf s'il existe un besoin réel pour elle.Si vous passez une heure de faire le changement, il doit produire 20 heures sauvé CPU de temps, au moins.Lorsque vous êtes à ce niveau, les meilleurs algorithmes sont très susceptibles de donner de meilleures économies.

Autres conseils

Je pense que je suis d'accord surtout avec @gnasher729, mais ces gens ce que vous soucier de "l'efficacité" serait critiquer à l'aide de la boucle for à tous, le "je" de la variable n'est pas ajouter quoi que ce soit ...

Pourquoi pas:

void blink3(int n) {
    while (n-- > 0) {
       blink_led();
    }
}

J'ai ajouté le "> 0" pour un couple de raisons:1) juste au cas où quelqu'un demande pour un montant NÉGATIF de clignotant, qui ne veulent pas rouler vers l'arrière pour 2 milliards de fois.2) c'est un peu plus évident pour le unitiated (peut-être).

Par la façon dont, dans l'exemple artificiel, le "blink_led()" fonction est bizarre et louche -- va probablement attendre à être en mesure de le voir aller à, puis s'éteint.Ainsi, "l'efficacité" est un peu hors de la table.

Mais, en général, pour la plupart des choses, l'efficacité est surtout sur la façon dont rapidement, il peut être codé et aussi (surtout) à quelle vitesse il est entendu.

Licencié sous: CC-BY-SA avec attribution
Non affilié à cs.stackexchange
scroll top