web-dev-qa-db-fra.com

Boucle avec un temps d'exécution nul

Est-il possible d'avoir une boucle qui a un temps d'exécution nul? Je pense que même une boucle vide devrait avoir un temps d'exécution car il y a une surcharge associée.

74
user3678189

Oui, selon la règle comme si le compilateur est seulement obligé d'émuler le comportement observable du code, donc si vous avez une boucle qui n'a pas tout comportement observable peut alors être complètement optimisé et aura donc effectivement un temps d'exécution nul.

Exemples

Par exemple, le code suivant:

int main()
{
  int j = 0 ;
  for( int i = 0; i < 10000; ++i )
  {
    ++j ;
  }
}

compilé avec gcc 4.9 en utilisant le -O3 flag finit par se réduire à ce qui suit (voir en direct):

main:
  xorl  %eax, %eax  #
  ret

Presque toutes les optimisations autorisées relèvent de la règle comme si , la seule exception que je sache est copie elison qui est autorisé à effectuer le comportement observable.

Certains autres exemples incluraient élimination du code mort qui peut supprimer le code dont le compilateur peut prouver qu'il ne sera jamais exécuté. Par exemple, même si la boucle suivante contient en effet un effet secondaire, elle peut être optimisée car nous pouvons prouver qu'elle ne sera jamais exécutée (voir en direct):

#include <stdio.h>

int main()
{
  int j = 0 ;
  if( false ) // The loop will never execute
  {
    for( int i = 0; i < 10000; ++i )
    {
      printf( "%d\n", j ) ;
      ++j ;
    }
  }
}

La boucle sera optimisée de la même manière que dans l'exemple précédent. Un exemple plus intéressant serait le cas où un calcul dans une boucle peut être déduit en une constante évitant ainsi le besoin d'une boucle ( ne savez pas de quelle catégorie d'optimisation il s'agit ), par exemple:

int j = 0 ;
for( int i = 0; i < 10000; ++i )
{
  ++j ;
}
printf( "%d\n", j ) ;

peut être optimisé pour (voir en direct):

movl    $10000, %esi    #,
movl    $.LC0, %edi #,
xorl    %eax, %eax  #
call    printf  #

Nous pouvons voir qu'il n'y a pas de boucle impliquée.

Où est la règle du as-if couverte par la norme

La règle comme si est traitée dans le projet de norme C99 section 5.1.2.3 Exécution du programme qui dit:

Dans la machine abstraite, toutes les expressions sont évaluées comme spécifié par la sémantique. Une implémentation réelle n'a pas besoin d'évaluer une partie d'une expression si elle peut en déduire que sa valeur n'est pas utilisée et qu'aucun effet secondaire nécessaire n'est produit (y compris ceux provoqués par l'appel d'une fonction ou l'accès à un objet volatil).

La règle comme si s'applique également à C++, gcc produira également le même résultat en mode C++. Le projet de norme C++ couvre cela dans la section 1.9 Exécution du programme :

Les descriptions sémantiques de la présente Norme internationale définissent une machine abstraite non déterministe paramétrée. La présente Norme internationale n'impose aucune exigence sur la structure des implémentations conformes. En particulier, ils n'ont pas besoin de copier ou d'émuler la structure de la machine abstraite. Des implémentations conformes sont plutôt nécessaires pour émuler (uniquement) le comportement observable de la machine abstraite, comme expliqué ci-dessous.5

121
Shafik Yaghmour

Oui - si le compilateur détermine que la boucle est du code mort (ne s'exécutera jamais), il ne générera pas de code pour cela. Cette boucle aura 0 temps d'exécution, bien qu'à proprement parler elle n'existe pas au niveau du code machine.

52

En plus des optimisations du compilateur, certaines architectures CPU, en particulier les DSP, ont zéro boucle en boucle , grâce à quoi une boucle avec un nombre fixe d'itérations est efficacement optimisée par le matériel, voir par exemple http://www.dsprelated.com/showmessage/20681/1.php

12
Paul R

Le compilateur n'est pas obligé d'évaluer l'expression, ou une partie d'une expression, qui n'a aucun effet secondaire et dont le résultat est rejeté.

Harbison et Steele, C: Un manuel de référence

3
Maxim Chetrusca