7 votes

Précision de la fonction clock() en C

J'ai un code qui essaie de déterminer le temps d'exécution d'un bloc de code.

#include <time.h>
#include <stdio.h>

int main()
{
   clock_t start_t, end_t, total_t;
   int i;

   start_t = clock(); //clock start
   printf("Starting of the program, start_t = %ld\n", start_t);

   printf("Going to scan a big loop, start_t = %ld\n", start_t);
   for(i=0; i< 10000000; i++)  //trying to determine execution time of this block
   {
   }
   end_t = clock(); //clock stopped
   printf("End of the big loop, end_t = %ld\n", end_t);

   total_t = (long int)(end_t - start_t);
   printf("Total time taken by CPU: %lu\n", total_t  );

   return(0);
}

Le résultat de l'extrait de code sur mon ordinateur est le suivant

Starting of the program, start_t = 8965
Going to scan a big loop, start_t = 8965
End of the big loop, end_t = 27259
Total time taken by CPU: 18294

Donc, si mon processeur tourne à 21 MHz et en supposant que c'est la seule chose qui est exécutée, chaque cycle machine serait approximativement égal à 47 nanosecondes, soit (18294 * 47) = 859818 nanosecondes.

Serait-ce le temps d'exécution de la boucle for de mon code ? Est-ce que je fais des suppositions incorrectes ici ?

5voto

Gilles Points 37537

L'unité de temps utilisée par le clock est arbitraire. Sur la plupart des plateformes, elle n'est pas liée à la vitesse du processeur. Elle est plus souvent liée à la fréquence d'une interruption de timer externe - qui peut être configurée en logiciel - ou à une valeur historique qui a été conservée pour des raisons de compatibilité au cours des années d'évolution du processeur. Vous devez utiliser la macro CLOCKS_PER_SEC à convertir en temps réel.

printf("Total time taken by CPU: %fs\n", (double)total_t / CLOCKS_PER_SEC);

La bibliothèque standard C a été conçue pour pouvoir être mise en œuvre sur une large gamme de matériel, y compris les processeurs qui ne possèdent pas de minuterie interne et qui dépendent d'un périphérique externe pour donner l'heure. De nombreuses plates-formes disposent de moyens plus précis pour mesurer le temps de l'horloge murale que time et des moyens plus précis de mesurer la consommation du CPU que clock . Par exemple, sur les systèmes POSIX (par exemple Linux et d'autres systèmes similaires à Unix), vous pouvez utiliser getrusage qui a une précision de l'ordre de la microseconde.

struct timeval start, end;
struct rusage usage;
getrusage(RUSAGE_SELF, &usage);
start = usage.ru_utime;
…
getrusage(RUSAGE_SELF, &usage);
end = usage.ru_utime;
printf("Total time taken by CPU: %fs\n", (double)(end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) / 1e-6);

Lorsqu'il est disponible, clock_gettime(CLOCK_THREAD_CPUTIME_ID) o clock_gettime(CLOCK_PROCESS_CPUTIME_ID) peut donner une meilleure précision. Il a une précision de l'ordre de la nanoseconde.

Notez la différence entre précision et exactitude : la précision est l'unité dans laquelle les valeurs sont rapportées. L'exactitude est la proximité des valeurs rapportées par rapport aux valeurs réelles. À moins que vous ne travailliez sur un système en temps réel En effet, il n'y a pas de garantie absolue quant au temps que prend un morceau de code, y compris l'invocation des fonctions de mesure elles-mêmes.

Certains processeurs ont cycle des horloges qui comptent les cycles du processeur plutôt que le temps de l'horloge murale, mais cela devient très spécifique au système.

Lorsque vous réalisez des benchmarks, n'oubliez pas que ce que vous mesurez est l'exécution de cet exécutable particulier sur ce processeur particulier dans ces circonstances particulières, et que les résultats peuvent ou non être généralisés à d'autres situations. Par exemple, la boucle vide dans votre question sera optimisée par la plupart des compilateurs, à moins que vous ne désactiviez les optimisations. Mesurer la vitesse d'un code non optimisé est généralement inutile. Même si vous ajoutez du travail réel dans la boucle, méfiez-vous des benchmarks jouets : ils n'ont souvent pas les mêmes caractéristiques de performance que le code réel. Sur les processeurs modernes haut de gamme tels que ceux que l'on trouve dans les PC et les smartphones, les benchmarks de code à forte intensité CPU sont souvent très sensibles aux effets de cache et les résultats peuvent dépendre de ce qui est en train de tourner sur le système, du modèle exact du processeur (en raison des différentes tailles et dispositions de cache), de l'adresse à laquelle le code est chargé, etc.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X