En utilisant uniquement ANSI C, existe-t-il un moyen de mesurer le temps avec une précision de quelques millisecondes ou plus? Je parcourais time.h mais je n'ai trouvé que des fonctions de seconde précision.
c
portability
time-precision
corto
la source
la source
Réponses:
Il n'y a pas de fonction ANSI C qui offre une résolution temporelle supérieure à 1 seconde, mais la fonction POSIX
gettimeofday
fournit une résolution en microsecondes. La fonction d'horloge ne mesure que le temps qu'un processus a passé à s'exécuter et n'est pas précise sur de nombreux systèmes.Vous pouvez utiliser cette fonction comme ceci:
Cela revient
Time elapsed: 1.000870
sur ma machine.la source
timeval::tv_usec
prend toujours moins d'une seconde, c'est en boucle. C'est-à-dire que pour prendre des différences de temps supérieures à 1 s, vous devez:long usec_diff = (e.tv_sec - s.tv_sec)*1000000 + (e.tv_usec - s.tv_usec);
timersub
fonction. Nous pouvons utiliser lestval_result
valeurs (tv_sec et tv_usec) telles quelles.la source
CLOCKS_PER_SEC / 1000
pourrait éventuellement être inexacte, ce qui pourrait affecter le résultat final (bien que dans mon expérienceCLOCKS_PER_SEC
ait toujours été un multiple de 1000). Faire(1000 * clock()) / CLOCKS_PER_SEC
est moins sensible à l'inexactitude de la division, mais d'un autre côté est plus susceptible de déborder. Juste quelques problèmes à considérer.J'utilise toujours la fonction clock_gettime (), renvoyant l'heure de l'horloge CLOCK_MONOTONIC. Le temps renvoyé est la durée, en secondes et en nanosecondes, depuis un moment non spécifié dans le passé, tel que le démarrage du système de l'époque.
la source
clock_gettime(CLOCK_MONOTONIC, ...)
et il y a même la macro de test de fonctionnalités_POSIX_MONOTONIC_CLOCK
.Mettre en œuvre une solution portable
Comme il a déjà été mentionné ici qu'il n'y a pas de solution ANSI appropriée avec une précision suffisante pour le problème de la mesure du temps, je veux écrire sur les moyens d'obtenir une solution de mesure du temps portable et, si possible, à haute résolution.
Horloge monotone et horodatage
De manière générale, il existe deux méthodes de mesure du temps:
Le premier utilise un compteur d'horloge monotone (parfois appelé compteur de ticks) qui compte les ticks avec une fréquence prédéfinie, donc si vous avez une valeur de ticks et que la fréquence est connue, vous pouvez facilement convertir les ticks en temps écoulé. Il n'est en fait pas garanti qu'une horloge monotone reflète en aucune façon l'heure actuelle du système, elle peut également compter les ticks depuis un démarrage du système. Mais cela garantit qu'une horloge est toujours exécutée de manière croissante quel que soit l'état du système. Habituellement, la fréquence est liée à une source matérielle haute résolution, c'est pourquoi elle offre une grande précision (dépend du matériel, mais la plupart du matériel moderne n'a aucun problème avec les sources d'horloge haute résolution).
La seconde méthode fournit une valeur d'heure (date) basée sur la valeur actuelle de l'horloge système. Il peut également avoir une résolution élevée, mais il présente un inconvénient majeur: ce type de valeur d'heure peut être affecté par différents ajustements de l'heure du système, c'est-à-dire le changement de fuseau horaire, le changement d'heure d'été (DST), la mise à jour du serveur NTP, l'hibernation du système, etc. sur. Dans certaines circonstances, vous pouvez obtenir une valeur de temps écoulé négative qui peut conduire à un comportement indéfini. En fait, ce type de source horaire est moins fiable que la première.
Ainsi, la première règle dans la mesure d'intervalle de temps est d'utiliser une horloge monotone si possible. Il a généralement une haute précision et est fiable de par sa conception.
Stratégie de repli
Lors de la mise en œuvre d'une solution portable, il vaut la peine d'envisager une stratégie de repli: utiliser une horloge monotone si disponible et une approche de repli vers l'horodatage s'il n'y a pas d'horloge monotone dans le système.
les fenêtres
Il existe un excellent article intitulé Acquérir des horodatages haute résolution sur MSDN sur la mesure du temps sous Windows, qui décrit tous les détails que vous pourriez avoir besoin de connaître sur la prise en charge logicielle et matérielle. Pour acquérir un horodatage de haute précision sous Windows, vous devez:
interroger une fréquence de minuterie (ticks par seconde) avec QueryPerformanceFrequency :
La fréquence du minuteur est fixée au démarrage du système, vous n'avez donc besoin de l'obtenir qu'une seule fois.
interrogez la valeur actuelle des graduations avec QueryPerformanceCounter :
mettre à l'échelle les graduations en fonction du temps écoulé, c'est-à-dire en microsecondes:
Selon Microsoft, vous ne devriez avoir aucun problème avec cette approche sur Windows XP et les versions ultérieures dans la plupart des cas. Mais vous pouvez également utiliser deux solutions de secours sous Windows:
GetTickCount
, mais elle est disponible à partir de Windows Vista et supérieur.OS X (macOS)
OS X (macOS) a ses propres unités de temps absolues Mach qui représentent une horloge monotone. La meilleure façon de commencer est l'article d'Apple Q&R technique QA1398: Mach Absolute Time Units qui décrit (avec les exemples de code) comment utiliser l'API spécifique à Mach pour obtenir des ticks monotones. Il y a aussi une question locale à ce sujet appelée alternative clock_gettime dans Mac OS X qui à la fin peut vous laisser un peu confus quoi faire avec le dépassement de valeur possible car la fréquence du compteur est utilisée sous la forme de numérateur et de dénominateur. Donc, un petit exemple comment obtenir le temps écoulé:
obtenir le numérateur et le dénominateur de la fréquence d'horloge:
Vous ne devez le faire qu'une seule fois.
interroger la valeur de graduation actuelle avec
mach_absolute_time
:mettre à l'échelle les graduations en fonction du temps écoulé, c'est-à-dire en microsecondes, en utilisant le numérateur et le dénominateur interrogés précédemment:
L'idée principale pour éviter un débordement est de réduire les graduations à la précision souhaitée avant d'utiliser le numérateur et le dénominateur. Comme la résolution initiale de la minuterie est en nanosecondes, nous la divisons par
1000
pour obtenir des microsecondes. Vous pouvez trouver la même approche utilisée dans time_mac.c de Chromium . Si vous avez vraiment besoin d'une précision à la nanoseconde, envisagez de lire le Comment puis-je utiliser mach_absolute_time sans déborder? .Linux et UNIX
L'
clock_gettime
appel est votre meilleur moyen sur n'importe quel système compatible POSIX. Il peut interroger l'heure à partir de différentes sources d'horloge, et celle dont nous avons besoin estCLOCK_MONOTONIC
. Tous les systèmes ne sont pas pris enclock_gettime
chargeCLOCK_MONOTONIC
, la première chose à faire est donc de vérifier sa disponibilité:_POSIX_MONOTONIC_CLOCK
est défini sur une valeur,>= 0
cela signifie qu'ilCLOCK_MONOTONIC
est disponible;si elle
_POSIX_MONOTONIC_CLOCK
est définie,0
cela signifie que vous devez en outre vérifier si cela fonctionne au moment de l'exécution, je suggère d'utilisersysconf
:L'utilisation de
clock_gettime
est assez simple:obtenir la valeur de temps:
J'ai réduit le temps en microsecondes ici.
calculer la différence avec la valeur de temps précédente reçue de la même manière:
La meilleure stratégie de repli est d'utiliser l'
gettimeofday
appel: ce n'est pas un monotone, mais il offre une assez bonne résolution. L'idée est la même qu'avecclock_gettime
, mais pour obtenir une valeur de temps, vous devez:Encore une fois, la valeur de temps est réduite en microsecondes.
SGI IRIX
IRIX a l'
clock_gettime
appel, mais il en manqueCLOCK_MONOTONIC
. Au lieu de cela, il a sa propre source d'horloge monotone définie queCLOCK_SGI_CYCLE
vous devez utiliser au lieu deCLOCK_MONOTONIC
avecclock_gettime
.Solaris et HP-UX
Solaris possède sa propre interface de minuterie haute résolution
gethrtime
qui renvoie la valeur actuelle du minuteur en nanosecondes. Bien que les nouvelles versions de Solaris puissent avoirclock_gettime
, vous pouvez vous en tenir àgethrtime
si vous avez besoin de prendre en charge les anciennes versions de Solaris.L'utilisation est simple:
HP-UX manque
clock_gettime
, mais il prend en chargegethrtime
ce que vous devez utiliser de la même manière que sur Solaris.BeOS
BeOS possède également sa propre interface de minuterie haute résolution
system_time
qui renvoie le nombre de microsecondes écoulées depuis le démarrage de l'ordinateur.Exemple d'utilisation:
OS / 2
OS / 2 possède sa propre API pour récupérer des horodatages de haute précision:
interroger une fréquence de minuterie (ticks par unité) avec
DosTmrQueryFreq
(pour le compilateur GCC):interroger la valeur actuelle des graduations avec
DosTmrQueryTime
:mettre à l'échelle les graduations en fonction du temps écoulé, c'est-à-dire en microsecondes:
Exemple d'implémentation
Vous pouvez jeter un oeil à la bibliothèque plibsys qui implémente toutes les stratégies décrites ci-dessus (voir ptimeprofiler * .c pour plus de détails).
la source
timespec_get
: stackoverflow.com/a/36095407/895245timespec_get
n'est pas monotone.timespec_get
à partir de C11Renvoie jusqu'à nanosecondes, arrondi à la résolution de l'implémentation.
On dirait une arnaque ANSI de POSIX '
clock_gettime
.Exemple: a
printf
est effectué toutes les 100 ms sur Ubuntu 15.10:Le projet de norme 7.27.2.5 C11 N1570 "La fonction timespec_get dit":
C ++ 11 a également obtenu
std::chrono::high_resolution_clock
: Minuterie haute résolution multiplateforme C ++implémentation de la glibc 2.21
Peut être trouvé sous
sysdeps/posix/timespec_get.c
comme:si clairement:
seulement
TIME_UTC
est actuellement pris en chargeil transmet à
__clock_gettime (CLOCK_REALTIME, ts)
, qui est une API POSIX: http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.htmlLinux x86-64 a un
clock_gettime
appel système.Notez qu'il ne s'agit pas d'une méthode de micro-benchmarking infaillible car:
man clock_gettime
indique que cette mesure peut présenter des discontinuités si vous modifiez certains paramètres d'heure système pendant l'exécution de votre programme. Cela devrait bien sûr être un événement rare et vous pourrez peut-être l'ignorer.cela mesure le temps du mur, donc si le planificateur décide d'oublier votre tâche, elle semblera fonctionner plus longtemps.
Pour ces raisons
getrusage()
pourrait s'agir d'un meilleur outil d'analyse comparative POSIX, malgré sa précision maximale inférieure à la microseconde.Plus d'informations sur: Mesurer le temps sous Linux - temps vs horloge vs getrusage vs clock_gettime vs gettimeofday vs timespec_get?
la source
La meilleure précision que vous puissiez obtenir est l'utilisation de l'instruction "rdtsc" uniquement x86, qui peut fournir une résolution au niveau de l'horloge (ne doit bien sûr prendre en compte le coût de l'appel rdtsc lui-même, qui peut être mesuré facilement sur démarrage de l'application).
Le problème principal ici est de mesurer le nombre d'horloges par seconde, ce qui ne devrait pas être trop difficile.
la source
La réponse acceptée est assez bonne, mais ma solution est plus simple: je viens de tester sous Linux, utilisez gcc (Ubuntu 7.2.0-8ubuntu3.2) 7.2.0.
Alse use
gettimeofday
, thetv_sec
is the part of second, and thetv_usec
is microsecondes , not millisecondes .Il imprime:
1522139691342 1522139692342
, exactement une seconde.la source
Sous windows:
la source