2017-05-09 2 views
1

Tous:Grande boucle a été ignorée par le compilateur Intel?

J'ai un très simple code de test C en utilisant le compilateur Intel pour faire un peu de temps pour une grande boucle pour le fonctionnement du point de flotteur, le code (test.c) est la suivante:

#include <sys/time.h> 
#include <time.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <math.h> 
#include <omp.h> 

int main(char *argc, char **argv) { 
     const long N = 1000000000; 
     double t0, t1, t2, t3; 
     double sum=0.0; 
     clock_t start, end; 
     struct timeval r_start, r_end; 
     long i; 
     gettimeofday(&r_start, NULL); 
     start = clock(); 
     for (i=0;i<N;i++) 
      sum += i*2.0+i/2.0; // doing some floating point operations 
     end = clock(); 
     gettimeofday(&r_end, NULL); 
     double cputime_elapsed_in_seconds = (end - start)/(double)CLOCKS_PER_SEC; 
     double realtime_elapsed_in_seconds = ((r_end.tv_sec * 1000000 + r_end.tv_usec) 
       - (r_start.tv_sec * 1000000 + r_start.tv_usec))/1000000.0; 
     printf("cputime_elapsed_in_sec: %e\n", cputime_elapsed_in_seconds); 
     printf("realtime_elapsed_in_sec: %e\n", realtime_elapsed_in_seconds); 
     //printf("sum= %4.3e\n", sum); 
     return 0; 
} 

Cependant quand j'essayé de compiler et exécuter avec Intel 13.0 compilateur, la grande boucle semble être ignoré et l'exécution a donné lieu à zéro moment:

$ icc test.c 
$ ./a.out 
cputime_elapsed_in_sec: 0.000000e+00 
realtime_elapsed_in_sec: 9.000000e-06 

Seulement si j'imprime la somme (ligne uncomment 26), la boucle effectivement être exe coupée:

$ icc test.c 
$ ./a.out 
cputime_elapsed_in_sec: 2.730000e+00 
realtime_elapsed_in_sec: 2.736198e+00 
sum= 1.250e+18 

La question est pourquoi la boucle ne semble pas exécutée si je n'imprime pas la valeur de la somme?

Le même problème ne se produit pas avec les compilateurs gcc-4.4.7, je suppose que le compilateur Intel aurait pu faire une certaine optimisation que si la variable n'est pas référencée, la boucle est probablement ignorée?

Les informations du système est le suivant:

$ uname -a 
Linux node001 2.6.32-642.11.1.el6.x86_64 #1 SMP Wed Oct 26 10:25:23 EDT 2016 x86_64 x86_64 x86_64 GNU/Linux 
$ icc -v 
icc version 13.0.0 (gcc version 4.4.7 compatibility) 
$ gcc -v 
Using built-in specs. 
Target: x86_64-redhat-linux 
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux 
Thread model: posix 
gcc version 4.4.7 20120313 (Red Hat 4.4.7-17) (GCC) 

Merci pour toutes suggestions!

Roy

+0

Quelle est votre question? – immibis

+0

Essayez de désactiver les optimisations et voyez si cela donne le résultat lorsque vous imprimez la somme: http://stackoverflow.com/questions/5765899/how-to-disable-compiler-optimizations-in-gcc –

+0

Une option consiste à déclarer ' sum' comme «volatile». – paddy

Répondre

6

Compte tenu de votre observation que l'impression de la valeur finale, il ralentit (a), il y a une assez bonne chance que l'Optimiseur est de déterminer que vous n'êtes pas réellement à l'aidesum quoi que ce soit après vous l'avez calculé, optimisant ainsi toute la boucle de calcul.

En fait, j'ai vu quelque chose de similaire il y a quelque temps lorsque nous avons testé les performances de la dernière machine VAX 11/780 reçue par notre université (montrant mon âge là-bas). Il a été plus rapide d'un facteur de plusieurs milliers de pour exactement la même raison, le nouveau compilateur d'optimisation ayant décidé que la boucle n'était pas réellement nécessaire.

Pour être certain, vous devez examiner la sortie de l'assemblage. Je crois que cela peut être fait avec icc en utilisant l'option -Fa <asmFileName>, puis en examinant le fichier dont vous avez utilisé le nom à <asmFileName>.


(a) L'autre possibilité que je pensais semble être réduit ici. C'était la possibilité que, étant donné la plage de i est constante (basée sur N) et que le calcul implique des constantes, il se peut que le compilateur lui-même ait calculé la valeur finale tout en la compilant, résultant en un simple opération de charge constante.

J'ai vu gcc faire ce genre de chose à son -O3 niveau d'optimisation «fou».

Je ne tiens pas compte de cette possibilité car l'impression de la valeur ne devrait probablement pas affecter cette opération.

+0

Merci pour la réponse, j'ai essayé -O1, -O2, -O3 sans la ligne de somme d'impression, le même résultat. Si complètement désactiver l'optimisation, en utilisant -O0, la boucle a été exécutée, donc je pense que oui, la réponse devrait être que le compilateur a optimisé l'ensemble de la boucle. –