9
votes

GCC optimise-t-il mon cycle avec condition?

J'ai le cycle suivant:

//condition will be set here to true or false

for (int i = 0; i < LARGE_NUMBER; i++) {
    if (condition) {
        //do foo
    } else {
        //do bar
    }
}


5 commentaires

Si "condition" ne change pas, pourquoi le mettriez-vous à l'intérieur "pour"?


@ Nacho4d: pour éviter la duplication de code (le pour en-tête et d'autres instructions en dehors du si mais à l'intérieur du pour pour pour )


Avez-vous déclaré condition comme volatile ?


@mvds: la condition n'est pas volatile, sinon le compilateur ne peut pas prédire sa valeur.


Je suis très satisfait des réponses, +1, merci pour tous.


3 Réponses :


8
votes

Tout compilateur d'optimisation décent fera cela si conditionner ne peut pas être modifié au cours de l'itération.

En outre, même si le compilateur ne le fait pas en fait, vous feriez bien de soutenir votre décision de réécrire le code à une forme lisible moins humaine avec des données durs du profilage. ne pas optimiser prématurément. Il ne vaut pas la peine de donner aux lecteurs du code A "hein?" moment afin de raser quelques millisecondes (et "lecteurs" vous inclut définitivement à une heure future).


0 commentaires

5
votes

Je ne ferai pas préconiser de prendre des mesures ici, par les arguments habituels "d'optimisation prématurée". Garder le code clair est le plus important, et si l'ensemble du programme est trop lent, vous voudrez peut-être profiler et trouver les goulots d'étranglement réels (que vous ne pouvez généralement pas deviner) après le débogage du programme.

Même si le compilateur n'oblise pas ce cas particulier pour vous, vous voudrez peut-être savoir que la CPU fait une forme de Prédiction des succursales qui réduira considérablement le temps nécessaire pour traiter la condition au cas où la condition est prévisible.

En effet, la plupart des instructions de processus CPU dans un pipeline et au moment où l'adresse de saut doit être déterminée, la condition La variable peut être inconnue. Cela causerait un stand de pipeline , et c'est là que la plupart des processeurs modernes essaient de deviner (de manière intelligente) où le programme va sauter. Si la variable de condition est bien connue (comme dans votre cas), la suppression sera parfaite.

Je doute donc que même avec un compilateur "muet", vous verriez une différence entre les deux options, au moins sur des machines modernes.


2 commentaires

En fait, la plupart des compilateurs doivent écrire deux boucles ici, en fonction de la valeur de la condition, s'il peut être prouvé que la condition ne change pas dans l'exécution de la boucle. Cela n'invalide pas ce que vous dites.


Totalement d'accord avec Matthieu. +1 pour la prédiction de la branche qui, dans ce cas, fait en effet la discussion discutable.



17
votes

Pour ceux qui ne souhaitent pas lire un poteau long, cette optimisation est appelée (en LLVM) Boop Unwitch .

Pourquoi ne pas demander à un compilateur? p>

int main(int argc, char**argv) {
  if (argc != 0)
  {
    int i = 0;
    if (argc % 2) {
      do {
        foo(argv[1]);
        ++i;
      } while (i != argc);
    } else {
      do {
        foo(argv[0]);
        ++i;
      } while (i != argc);
    }
  }
  return 0;
}
  • entrée code>: Vérifiez si argc code> est égal à 0, si c'est le cas, accédez à BB5 code> (sortie) d'autre part à bb.nph code> li>
  • bb.nph code>: calculez la valeur de condition code>, si c'est vrai, accédez à bb3.us code> sinon aller to bb3 code> li>
  • bb3.us code> et bb3 code>: boucles pour la condition vraie et fausse respectivement li>
  • BB5 code>: Quitter li> ul>

    Un compilateur peut trop transformer votre code comment il veut, tant que l'effet est similaire à ce que vous avez demandé. Dans ce cas, il a réécrit efficacement le code comme suit: p> xxx pré>

    C'est une forme d'optimisation de la boucle invariante, combinée ici avec un premier contrôle pour éviter de calculer la condition si la boucle est Ne pas être exécuté. P>

    Pour ceux d'entre nous qui penseraient que la première solution est plus claire, nous sommes assez heureux d'avoir le compilateur faire l'optimisation Nitty Gritty pour nous! P> P> >


1 commentaires

Note rapide Cela pourrait être encore plus laid, en fait, si le compilateur se déroulait en boucle (pour éviter de vérifier s'il doit continuer à boucler à chaque itération). Si vous souhaitez examiner le déroulement manuel, recherchez le périphérique de Duff, et vous conviendrez probablement que c'est mieux si le compilateur le fait.