J'ai un programme C qui vise à être exécuté en parallèle sur plusieurs processeurs. Je dois pouvoir enregistrer le temps d'exécution (qui peut aller de 1 seconde à plusieurs minutes). J'ai cherché des réponses, mais elles semblent toutes suggérer d'utiliser la clock()
fonction, ce qui implique ensuite de calculer le nombre d'horloges prises par le programme divisé par la Clocks_per_second
valeur.
Je ne sais pas comment la Clocks_per_second
valeur est calculée?
En Java, je prends juste l'heure actuelle en millisecondes avant et après l'exécution.
Y a-t-il une chose similaire en C? J'ai jeté un coup d'œil, mais je n'arrive pas à trouver un moyen d'obtenir quelque chose de mieux qu'une deuxième résolution.
Je suis également conscient qu'un profileur serait une option, mais je cherche à implémenter un minuteur moi-même.
Merci
la source
Réponses:
CLOCKS_PER_SEC
est une constante qui est déclarée en<time.h>
. Pour obtenir le temps CPU utilisé par une tâche dans une application C, utilisez:Notez que cela renvoie l'heure comme un type à virgule flottante. Cela peut être plus précis qu'une seconde (par exemple, vous mesurez 4,52 secondes). La précision dépend de l'architecture; sur les systèmes modernes, vous obtenez facilement 10 ms ou moins, mais sur les machines Windows plus anciennes (de l'ère Win98), elle était plus proche de 60 ms.
clock()
est la norme C; ça marche "partout". Il existe des fonctions spécifiques au système, telles quegetrusage()
sur les systèmes de type Unix.Java
System.currentTimeMillis()
ne mesure pas la même chose. Il s'agit d'une "horloge murale": elle peut vous aider à mesurer le temps nécessaire au programme pour s'exécuter, mais elle ne vous indique pas combien de temps CPU a été utilisé. Sur un système multitâche (c'est-à-dire tous), ceux-ci peuvent être très différents.la source
clock()
renvoie une heure dans une échelle interne appelée "horloges", etCLOCKS_PER_SEC
est le nombre d'horloges par seconde, donc la division parCLOCKS_PER_SEC
donne une heure en secondes. Dans le code ci-dessus, la valeur est undouble
afin que vous puissiez la mettre à l'échelle à volonté.CLOCKS_PER_SEC
est unlong int
avec la valeur1000000
, donnant le temps en microsecondes lorsqu'il n'est pas divisé; pas les cycles d'horloge du processeur. Par conséquent, il n'a pas besoin de tenir compte de la fréquence dynamique car l'horloge ici est en microsecondes (peut-être des cycles d'horloge pour un processeur à 1 MHz?) J'ai fait un court programme C en imprimant cette valeur et c'était 1000000 sur mon ordinateur portable i7-2640M, avec une fréquence dynamique permettant de 800 MHz à 2,8 GHz, même en utilisant Turbo Boost pour aller jusqu'à 3,5 GHz.Si vous utilisez le shell Unix pour l'exécution, vous pouvez utiliser la commande time.
Faire
en supposant a.out que l'exécutable vous donnera le temps nécessaire pour exécuter cette
la source
perf stat ./a.out
pour obtenir des compteurs de performances matérielles pour les échecs de cache et les erreurs de prédiction des succursales et IPC.En vanille nature C:
la source
Vous voulez fonctionnellement cela:
Notez que cela mesure en microsecondes, pas seulement en quelques secondes.
la source
gettimeofday
est obsolète et n'est pas recommandé pour le nouveau code. Sa page de manuel POSIX recommande plutôt clock_gettime , ce qui vous permet de demander queCLOCK_MONOTONIC
cela ne soit pas affecté par les modifications de l'horloge système, et donc c'est mieux comme intervalle de temps. (Voir la réponse de JohnSll ). Sur les systèmes Linux modernes, par exemple, gettimeofday est essentiellement un wrapper pour clock_gettime qui convertit les nanosecondes en microsecondes.La plupart des programmes simples ont un temps de calcul en millisecondes. Donc, je suppose que vous trouverez cela utile.
Si vous souhaitez calculer le temps d'exécution de l'ensemble du programme et que vous êtes sur un système Unix, exécutez votre programme en utilisant la commande time comme celle-ci
time ./a.out
la source
Beaucoup de réponses ont été suggérées
clock()
, puisCLOCKS_PER_SEC
detime.h
. C'est probablement une mauvaise idée, car voici ce que/bits/time.h
dit mon dossier:Donc,
CLOCKS_PER_SEC
pourrait être défini comme 1000000, selon les options que vous utilisez pour compiler, et cela ne semble donc pas être une bonne solution.la source
CLOCK_PER_SEC==1000000
, mais en même temps, ils utilisent tous une précision de 1 µs pour leur implémentation clock (); au fait, il a la belle propriété de réduire les problèmes de partage. Si vous souhaitez mesurer des événements potentiellement très rapides, disons en dessous de 1 ms, vous devez d'abord vous soucier de la précision (ou résolution) de la fonction horloge (), qui est nécessairement plus grossière que 1µs en Posix, mais est souvent aussi beaucoup plus grossière; la solution habituelle consiste à exécuter le test plusieurs fois; la question posée ne semble cependant pas l'exiger.clock()
, si vous divisez cette valeur avecCLOCK_PER_SEC
vous, vous êtes assuré d'obtenir le temps en secondes que le processeur a pris. La responsabilité de mesurer la vitesse d'horloge réelle relève de laclock()
fonction et non de la vôtre.La réponse de Thomas Pornin sous forme de macros:
Utilisez-le comme ceci:
Production:
la source
Vous devez tenir compte du fait que mesurer le temps exécution d'un programme dépend beaucoup de la charge de la machine à ce moment précis.
Sachant que, la manière d'obtenir l'heure actuelle en C peut être réalisée de différentes manières, la plus simple est:
J'espère que ça aide.
Cordialement!
la source
(Toutes les réponses manquent ici, si votre administrateur système modifie l'heure système ou si votre fuseau horaire a des heures d'hiver et d'été différentes. Par conséquent ...)
Sur Linux:
clock_gettime(CLOCK_MONOTONIC_RAW, &time_variable);
Cela n'est pas affecté si l'administrateur système modifie l'heure, ou si vous vivez dans un pays avec une heure d'hiver différente de l'heure d'été, etc.man clock_gettime
États:la source
(end.tv_nsec - begin.tv_nsec) / 1000000000.0
résulterait -il pas0
toujours?double
littéral déclenche int oulong
endouble
conversion avant la division. Bien sûr, vous pouvez simplement vous en tenir à un entier et imprimer latv_sec
partie puis la partie fractionnaire avec zéro comme%ld.%09ld
, mais la conversion en double est facile et 53 bits de précision sont généralement suffisants pour les temps de référence.timespec_subtract
comme celuitimeval_subtract
suggéré dans le manuel de la glibc : gnu.org/software/libc/manual/html_node/Elapsed-Time.html )ANSI C spécifie uniquement les secondes fonctions temporelles de précision. Cependant, si vous exécutez dans un environnement POSIX, vous pouvez utiliser gettimeofday () qui fournit une résolution en microsecondes du temps écoulé depuis l'époque UNIX.
En guise de remarque, je ne recommanderais pas d'utiliser clock () car il est mal implémenté sur de nombreux systèmes (sinon tous?) Et n'est pas précis, outre le fait qu'il se réfère uniquement au temps que votre programme a passé sur le CPU et pas la durée de vie totale du programme, ce qui, selon votre question, est ce que je suppose que vous aimeriez mesurer.
la source
Toutes les solutions ne fonctionnent pas dans mon système.
Je peux utiliser
la source
time_t
valeurs sous forme de double. Étant donné que lestime_t
valeurs ne sont précises qu'à une seconde, elles ont une valeur limitée pour imprimer le temps pris par les programmes à exécution courte, bien qu'elles puissent être utiles pour les programmes qui s'exécutent sur de longues périodes.clock_t
s àdifftime
semble fonctionner pour moi avec la précision d'un centième de seconde. C'est sur Linux x86. Je ne peux pas non plus obtenir la soustraction destop
etstart
travailler.difftime()
clock() / CLOCKS_PER_SEC
, car il attend des secondes.la source
J'ai trouvé que l'horloge habituelle (), tout le monde le recommande ici, pour une raison quelconque, s'écarte énormément d'une exécution à l'autre, même pour du code statique sans aucun effet secondaire, comme dessiner à l'écran ou lire des fichiers. Cela pourrait être dû au fait que le processeur change les modes de consommation d'énergie, que le système d'exploitation donne différentes priorités, etc.
Ainsi, le seul moyen d'obtenir de manière fiable le même résultat à chaque fois avec clock () est d'exécuter le code mesuré en boucle plusieurs fois (pendant plusieurs minutes), en prenant des précautions pour empêcher le compilateur de l'optimiser: les compilateurs modernes peuvent précalculer le code sans effets secondaires en cours d'exécution dans une boucle, et déplacez-le hors de la boucle., comme c'est-à-dire en utilisant une entrée aléatoire pour chaque itération.
Une fois que suffisamment d'échantillons ont été collectés dans un tableau, on trie ce tableau et prend l'élément central, appelé médiane. La médiane est meilleure que la moyenne, car elle élimine les écarts extrêmes, comme par exemple l'antivirus occupant tout le processeur ou le système d'exploitation faisant une mise à jour.
Voici un utilitaire simple pour mesurer les performances d'exécution du code C / C ++, en faisant la moyenne des valeurs proches de la médiane: https://github.com/saniv/gauge
Je suis moi-même toujours à la recherche d'un moyen plus robuste et plus rapide de mesurer le code. On pourrait probablement essayer d'exécuter le code dans des conditions contrôlées sur du métal nu sans aucun système d'exploitation, mais cela donnera un résultat irréaliste, car en réalité, le système d'exploitation s'implique.
x86 a ces compteurs de performances matérielles, qui incluent le nombre réel d'instructions exécutées, mais ils sont difficiles à accéder sans l'aide du système d'exploitation, difficiles à interpréter et ont leurs propres problèmes ( http://archive.gamedev.net/archive/reference/articles /article213.html ). Ils pourraient tout de même être utiles pour enquêter sur la nature du col de la bouteille (accès aux données ou calculs réels sur ces données).
la source
performance
) ou plusieurs dizaines de millisecondes. en.wikipedia.org/wiki/Dynamic_frequency_scaling . Et oui, la performance médiane est généralement un bon choix; le haut de gamme a généralement des pointes d'interférence.main
qui prend un argument et renvoie un résultat, et n'utilisez pas l'optimisation de la liaison. Ensuite, le compilateur ne peut pas l'intégrer dans l'appelant. Ne fonctionne que si la fonction inclut déjà une sorte de boucle, sinon la surcharge appel / ret est trop élevée.Certains pourraient trouver un autre type d'entrée utile: on m'a donné cette méthode de mesure du temps dans le cadre d'un cours universitaire sur la programmation GPGPU avec NVidia CUDA ( description du cours ). Il combine des méthodes vues dans des articles précédents, et je le poste simplement parce que les exigences lui donnent de la crédibilité:
Je suppose que vous pourriez multiplier par exemple
1.0 / 1000.0
pour obtenir l'unité de mesure qui convient à vos besoins.la source
clock_gettime
place, ce qui vous permet de demander queCLOCK_MONOTONIC
cela ne soit pas affecté par les modifications de l'horloge système, et donc c'est mieux comme minuterie d'intervalle. Sur les systèmes Linux modernes, par exemple,gettimeofday
est essentiellement un wrapper pourclock_gettime
convertir les nanosecondes en microsecondes. (Voir la réponse de JohnSll).timeval_subtract
.Comparaison du temps d'exécution du tri à bulles et du tri par sélection J'ai un programme qui compare le temps d'exécution du tri à bulles et du tri par sélection. Pour connaître l'heure d'exécution d'un bloc de code, calculer l'heure avant et après le bloc en
Exemple de code:
la source