IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Mesurer le temps absolu écoulé avec clock_gettime() VS gettimeofday()


Sujet :

C

  1. #1
    Membre confirmé

    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Février 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2005
    Messages : 464
    Points : 646
    Points
    646
    Par défaut Mesurer le temps absolu écoulé avec clock_gettime() VS gettimeofday()
    Bonjour,

    Il y a des personnes qui critiquent la mesure de temps écoulé avec gettimeofday() et préfèrent utiliser clock_gettime() avec la raison que celle-ci est plus précise, mais à quel point ?
    J'ai écrit le code ci-dessous pour faire des tests de comparaison.

    Description du code :
    > Changement de la police d'ordonnancement du processus (il faut avoir des droits 'root').
    > récupérer la résolution temporelle du système.
    > utiliser nanosleep() pour dormir une période(= résolution temporelle du système.) mesurée avec clock_gettime et gettimeofday()
    > utiliser nanosleep() pour dormir une période(= résolution temporelle du système /2) mesurée avec clock_gettime et gettimeofday().

    Analyse du résultat :
    D'après le manpage nanosleep() est soumis à la résolution temporelle du système sauf pour le cas expectionnelle de petite temporisation ou la boucle est active, donc vous ne pourrez jamais dormir une période en deça de cette résolution (d'où le même résultat quand on divise par deux la période).

    Mais en plus de cela il faut ajouter au temps du sommeil le temps pour redémarrer le processus ("sortir du sleep et continuer le code") qui est au plus égal à la résolution temporelle du système, ce qui explique que les temps mesurés sont toujours supérieurs à la milliseconde mais restent en deça de la milliseconde de plus .
    Finalement la différence de mesure est très faible (0.3 % d'écart) et donc il est possible d'utiliser clock_gettime() comme gettimeofday() pour des mesures à la microsecondes.
    Enfin, je n'ai pas constaté que le nanosleep était plus précis pour des petites temporisations. Si des personnes ont des idées là-dessus ?

    Ci-dessous le code (des commentaires sont ajoutés pour une autre méthode de mesure) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    #include <stdio.h>
    #include <time.h>
    #include <sys/time.h>
    #include <sched.h>
    #include <errno.h>
    #include <string.h>
     
     
    // Linux : link with librt : gcc -O3 -Wall main.c -lrt
    //  add a random arg to set SCHED_FIFO priority
     
    /*
    	TEST with :
    	Env: 
    		Linux sli-linux 2.6.13CIO-SLI-15-default #5 Thu Apr 5 11:29:06 CEST 2007 i686 i686 i386 GNU/Linux
    	Processor :
    		vendor_id       : GenuineIntel
    		cpu family      : 15
    		model           : 2
    		model name      : Intel(R) Pentium(R) 4 CPU 2.00GHz
    		stepping        : 4
    		cpu MHz         : 1994.327
    		cache size      : 512 KB
    	gcc version 4.0.2 20050901 (prerelease) (SUSE Linux)
     
    	RESULTS :
    	sli@sli-linux:~/developpement/my_tests/test_clock_gettime> ./a.out
    	No sheduling change
    	resolution : 0 s 999848 nsec
    	classic scheduling, nanosleep(0 s, 999848 nsec), clock_gettime interval : 0 s 1408000 nsec
    	classic scheduling, nanosleep(0 s, 999848 nsec), gettimeofday interval : 0 s 1406 usec
    	relative accuracy of gettimeofday() to clockgettime() : -0.142248 %
    	classic scheduling, nanosleep(0 s, 499924 nsec), clock_gettime interval : 0 s 1515000 nsec
    	classic scheduling, nanosleep(0 s, 499924 nsec), gettimeofday interval : 0 s 1515 usec
    	relative accuracy of gettimeofday() to clockgettime() : 0.000000 %
    	sli@sli-linux:~/developpement/my_tests/test_clock_gettime> sudo ./a.out r
    	Password:
    	setting scheduling to FIFO
    	resolution : 0 s 999848 nsec
    	classic scheduling, nanosleep(0 s, 999848 nsec), clock_gettime interval : 0 s 1168000 nsec
    	classic scheduling, nanosleep(0 s, 999848 nsec), gettimeofday interval : 0 s 1166 usec
    	relative accuracy of gettimeofday() to clockgettime() : -0.171527 %
    	classic scheduling, nanosleep(0 s, 499924 nsec), clock_gettime interval : 0 s 1939000 nsec
    	classic scheduling, nanosleep(0 s, 499924 nsec), gettimeofday interval : 0 s 1939 usec
    	relative accuracy of gettimeofday() to clockgettime() : 0.000000 %
     
    	CONCLUSION :
    	Whatever scheduling is sleep() resolution time is system resolution time (here 1ms)
    	The difference beetwenn clock_gettime() and gettimeofday() is negligible
    	However clock_gettime() is compatible SUSv2, POSIX 1003.1-2001 (manpages), when gettimeofday() not ( SVr4, BSD 4.3), and for portability reason it is always better to use POSIX functions. For linux you will have to check the librt availability.
     
    	TODO :
    		Make two list of measures and compare mediums
    		Check that with sched FIFO and <2ms tempo nanosleep() is more accurate.
    */
    int main (int argc, char * argv[])
    {
    	clockid_t clk_id = CLOCK_REALTIME ;
    	// resolution
    	struct timespec res, tp_start, tp_end ;
    	struct timeval tv_start, tv_end ;
    	// nanosleep
    	struct timespec req, rem, tick_adj ;
    	// shed
    	struct sched_param param ;
    	int i ;
    	float accuracy ;
     
    	// Set RT priority ?
    	if (argc > 1)
    	{
    		printf("setting scheduling to FIFO\n") ;
    		if (sched_getparam(0, &param ) == -1)	
    		{
    			printf("error shed_get  : %s\n", strerror(errno)) ;
    			return -1 ;
    		}
    		// manpage says priority must be >0 for fifo sched
    		param.sched_priority = 1 ;
    		if ( sched_setscheduler(0, SCHED_FIFO, &param) == -1)
    		{
    			printf("error shed_set  : %s\n", strerror(errno)) ;
                            return -1 ;
    		}
    	}
    	else
    	{
    		printf("No sheduling change\n") ;
    	}
     
    	if ( clock_getres(clk_id, &res) == 0)
    	{
    		printf("resolution : %ld s %ld nsec\n", res.tv_sec, res.tv_nsec) ;
    	}	
    	else
    	{
    		printf("err getting resolution : %s\n", strerror(errno));
    		return -1 ;
    	}
     
    	for (i = 1 ; i < 3 ; i++)
    	{
    		// manpage says : nanosleep sleep at least a time slice (i386=10ms), unless SCHED_FIFO/SCHED_RR for process (in this case 1us)
     
    		// Now sleep a 'RT' time resolution / i to check nanosleep resolution in the Linux Classic Scheduling
    	    req = res ;
    		req.tv_sec /= i ;
    		req.tv_nsec /= i ;
     
    		// put a non-active sleep here to start on a tick.
    		tick_adj.tv_sec = 0 ;
    		tick_adj.tv_nsec = 20 * 1000000 ;
    		nanosleep(&tick_adj, NULL) ;
     
    		// We 'hope' that execution of clock_gettime+gettimeofday+nanosleep < tick duration
    		clock_gettime(clk_id,&tp_start) ;
    		gettimeofday(&tv_start, NULL) ;
    		if(nanosleep(&req, &rem) == 0)
    		{
    			clock_gettime(clk_id,&tp_end) ;
    			gettimeofday(&tv_end, NULL) ;
    			printf("classic scheduling, nanosleep(%ld s, %ld nsec), clock_gettime interval : %ld s %ld nsec\n", 
    				res.tv_sec / i, res.tv_nsec / i ,
    				tp_end.tv_sec - tp_start.tv_sec, tp_end.tv_nsec - tp_start.tv_nsec) ;	
     
    			printf("classic scheduling, nanosleep(%ld s, %ld nsec), gettimeofday interval : %ld s %ld usec\n",
    					res.tv_sec /i , res.tv_nsec /i ,
    					tv_end.tv_sec - tv_start.tv_sec, tv_end.tv_usec - tv_start.tv_usec) ;
     
    			// printf relative accuracy (rounded to us) :
    			accuracy = 1.0 - (float)((tp_end.tv_sec - tp_start.tv_sec)*1000000 + (tp_end.tv_nsec - tp_start.tv_nsec)/1000) / (float)( (tv_end.tv_sec - tv_start.tv_sec)*1000000 + tv_end.tv_usec - tv_start.tv_usec) ;		
    			accuracy *= 100.0 ;
    			printf("relative accuracy of gettimeofday() to clockgettime() : %f %% \n", accuracy) ;
    		}
    		else
    		{
    			printf("interrupted sleep, aborting : %s\n", strerror(errno)) ;
    		}
    	}	
     
    	return 0 ;
    }

  2. #2
    Membre expérimenté

    Homme Profil pro
    Retraite
    Inscrit en
    Octobre 2005
    Messages
    487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Retraite
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 487
    Points : 1 374
    Points
    1 374
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par bizulk Voir le message
    Bonjour,

    Il y a des personnes qui critiquent la mesure de temps écoulé avec gettimeofday() et préfèrent utiliser clock_gettime() avec la raison que celle-ci est plus précise, mais à quel point ?
    J'ai écrit le code ci-dessous pour faire des tests de comparaison.

    Description du code :
    > Changement de la police d'ordonnancement du processus (il faut avoir des droits 'root').
    > récupérer la résolution temporelle du système.
    > utiliser nanosleep() pour dormir une période(= résolution temporelle du système.) mesurée avec clock_gettime et gettimeofday()
    > utiliser nanosleep() pour dormir une période(= résolution temporelle du système /2) mesurée avec clock_gettime et gettimeofday().

    Analyse du résultat :
    D'après le manpage nanosleep() est soumis à la résolution temporelle du système sauf pour le cas expectionnelle de petite temporisation ou la boucle est active, donc vous ne pourrez jamais dormir une période en deça de cette résolution (d'où le même résultat quand on divise par deux la période).

    Mais en plus de cela il faut ajouter au temps du sommeil le temps pour redémarrer le processus ("sortir du sleep et continuer le code") qui est au plus égal à la résolution temporelle du système, ce qui explique que les temps mesurés sont toujours supérieurs à la milliseconde mais restent en deça de la milliseconde de plus .
    Finalement la différence de mesure est très faible (0.3 % d'écart) et donc il est possible d'utiliser clock_gettime() comme gettimeofday() pour des mesures à la microsecondes.
    Enfin, je n'ai pas constaté que le nanosleep était plus précis pour des petites temporisations. Si des personnes ont des idées là-dessus ?

    Ci-dessous le code (des commentaires sont ajoutés pour une autre méthode de mesure) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    #include <stdio.h>
    #include <time.h>
    #include <sys/time.h>
    #include <sched.h>
    #include <errno.h>
    #include <string.h>
     
     
    // Linux : link with librt : gcc -O3 -Wall main.c -lrt
    //  add a random arg to set SCHED_FIFO priority
     
    /*
    	TEST with :
    	Env: 
    		Linux sli-linux 2.6.13CIO-SLI-15-default #5 Thu Apr 5 11:29:06 CEST 2007 i686 i686 i386 GNU/Linux
    	Processor :
    		vendor_id       : GenuineIntel
    		cpu family      : 15
    		model           : 2
    		model name      : Intel(R) Pentium(R) 4 CPU 2.00GHz
    		stepping        : 4
    		cpu MHz         : 1994.327
    		cache size      : 512 KB
    	gcc version 4.0.2 20050901 (prerelease) (SUSE Linux)
     
    	RESULTS :
    	sli@sli-linux:~/developpement/my_tests/test_clock_gettime> ./a.out
    	No sheduling change
    	resolution : 0 s 999848 nsec
    	classic scheduling, nanosleep(0 s, 999848 nsec), clock_gettime interval : 0 s 1408000 nsec
    	classic scheduling, nanosleep(0 s, 999848 nsec), gettimeofday interval : 0 s 1406 usec
    	relative accuracy of gettimeofday() to clockgettime() : -0.142248 %
    	classic scheduling, nanosleep(0 s, 499924 nsec), clock_gettime interval : 0 s 1515000 nsec
    	classic scheduling, nanosleep(0 s, 499924 nsec), gettimeofday interval : 0 s 1515 usec
    	relative accuracy of gettimeofday() to clockgettime() : 0.000000 %
    	sli@sli-linux:~/developpement/my_tests/test_clock_gettime> sudo ./a.out r
    	Password:
    	setting scheduling to FIFO
    	resolution : 0 s 999848 nsec
    	classic scheduling, nanosleep(0 s, 999848 nsec), clock_gettime interval : 0 s 1168000 nsec
    	classic scheduling, nanosleep(0 s, 999848 nsec), gettimeofday interval : 0 s 1166 usec
    	relative accuracy of gettimeofday() to clockgettime() : -0.171527 %
    	classic scheduling, nanosleep(0 s, 499924 nsec), clock_gettime interval : 0 s 1939000 nsec
    	classic scheduling, nanosleep(0 s, 499924 nsec), gettimeofday interval : 0 s 1939 usec
    	relative accuracy of gettimeofday() to clockgettime() : 0.000000 %
     
    	CONCLUSION :
    	Whatever scheduling is sleep() resolution time is system resolution time (here 1ms)
    	The difference beetwenn clock_gettime() and gettimeofday() is negligible
    	However clock_gettime() is compatible SUSv2, POSIX 1003.1-2001 (manpages), when gettimeofday() not ( SVr4, BSD 4.3), and for portability reason it is always better to use POSIX functions. For linux you will have to check the librt availability.
     
    	TODO :
    		Make two list of measures and compare mediums
    		Check that with sched FIFO and <2ms tempo nanosleep() is more accurate.
    */
    int main (int argc, char * argv[])
    {
    	clockid_t clk_id = CLOCK_REALTIME ;
    	// resolution
    	struct timespec res, tp_start, tp_end ;
    	struct timeval tv_start, tv_end ;
    	// nanosleep
    	struct timespec req, rem, tick_adj ;
    	// shed
    	struct sched_param param ;
    	int i ;
    	float accuracy ;
     
    	// Set RT priority ?
    	if (argc > 1)
    	{
    		printf("setting scheduling to FIFO\n") ;
    		if (sched_getparam(0, &param ) == -1)	
    		{
    			printf("error shed_get  : %s\n", strerror(errno)) ;
    			return -1 ;
    		}
    		// manpage says priority must be >0 for fifo sched
    		param.sched_priority = 1 ;
    		if ( sched_setscheduler(0, SCHED_FIFO, &param) == -1)
    		{
    			printf("error shed_set  : %s\n", strerror(errno)) ;
                            return -1 ;
    		}
    	}
    	else
    	{
    		printf("No sheduling change\n") ;
    	}
     
    	if ( clock_getres(clk_id, &res) == 0)
    	{
    		printf("resolution : %ld s %ld nsec\n", res.tv_sec, res.tv_nsec) ;
    	}	
    	else
    	{
    		printf("err getting resolution : %s\n", strerror(errno));
    		return -1 ;
    	}
     
    	for (i = 1 ; i < 3 ; i++)
    	{
    		// manpage says : nanosleep sleep at least a time slice (i386=10ms), unless SCHED_FIFO/SCHED_RR for process (in this case 1us)
     
    		// Now sleep a 'RT' time resolution / i to check nanosleep resolution in the Linux Classic Scheduling
    	    req = res ;
    		req.tv_sec /= i ;
    		req.tv_nsec /= i ;
     
    		// put a non-active sleep here to start on a tick.
    		tick_adj.tv_sec = 0 ;
    		tick_adj.tv_nsec = 20 * 1000000 ;
    		nanosleep(&tick_adj, NULL) ;
     
    		// We 'hope' that execution of clock_gettime+gettimeofday+nanosleep < tick duration
    		clock_gettime(clk_id,&tp_start) ;
    		gettimeofday(&tv_start, NULL) ;
    		if(nanosleep(&req, &rem) == 0)
    		{
    			clock_gettime(clk_id,&tp_end) ;
    			gettimeofday(&tv_end, NULL) ;
    			printf("classic scheduling, nanosleep(%ld s, %ld nsec), clock_gettime interval : %ld s %ld nsec\n", 
    				res.tv_sec / i, res.tv_nsec / i ,
    				tp_end.tv_sec - tp_start.tv_sec, tp_end.tv_nsec - tp_start.tv_nsec) ;	
     
    			printf("classic scheduling, nanosleep(%ld s, %ld nsec), gettimeofday interval : %ld s %ld usec\n",
    					res.tv_sec /i , res.tv_nsec /i ,
    					tv_end.tv_sec - tv_start.tv_sec, tv_end.tv_usec - tv_start.tv_usec) ;
     
    			// printf relative accuracy (rounded to us) :
    			accuracy = 1.0 - (float)((tp_end.tv_sec - tp_start.tv_sec)*1000000 + (tp_end.tv_nsec - tp_start.tv_nsec)/1000) / (float)( (tv_end.tv_sec - tv_start.tv_sec)*1000000 + tv_end.tv_usec - tv_start.tv_usec) ;		
    			accuracy *= 100.0 ;
    			printf("relative accuracy of gettimeofday() to clockgettime() : %f %% \n", accuracy) ;
    		}
    		else
    		{
    			printf("interrupted sleep, aborting : %s\n", strerror(errno)) ;
    		}
    	}	
     
    	return 0 ;
    }
    CONCLUSION :
    Whatever scheduling is sleep() resolution time is system resolution time (here 1ms)
    The difference beetwenn clock_gettime() and gettimeofday() is negligible
    However clock_gettime() is compatible SUSv2, POSIX 1003.1-2001 (manpages), when gettimeofday() not ( SVr4, BSD 4.3), and for portability reason it is always better to use POSIX functions. For linux you will have to check the librt availability.
    dernièrement je me suis penché pour faire un n° de session unique avec :

    time_t now = time(0);
    tm *ltm = localtime(&now);

    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);

    strftime(sessiond, 14, "%4Y%2m%2d%2H%2M%2S", ltm);
    sprintf(session,"%14s%012lld",sessiond,( long long int)ts.tv_nsec);

    bref j'ai testé aussi :
    //gettimeofday(&tp, NULL);
    //long int ms = tp.tv_sec * 1000 + tp.tv_usec / 1000;

    20150707215638000000062921---226 gettimeofday

    20150707215638000062974083---326 CLOCK_REALTIME


    pour découvrir sur plus de 5h de lecture dans les documentations un gars qui rappel que Linux par exemple travail avec des cycles de 10 ms mais que l'on peux récupéré la nanoseconde (je suis sur un 64bits)
    j'ai testé sur AS400 aussi là il travail a la nanoseconde effectivement il y a une différence

    mais tout cela il ne faut pas oublier l'horloge de cadencement de nos machine peut être avec une horloge plus rapide et le cycle du kernel .... la signification prendra de la valeur

    merci votre teste m'a confirmé .... je stop là en ce qui me concerne j'obtiens un n° unique.

    un article intéressant:
    http://okki666.free.fr/docmaster/articles/linux125.html

    http://juliusdavies.ca/posix_clocks/...linux_faq.html

Discussions similaires

  1. Calcul du temps écoulé avec critères spécifiques
    Par kedmard dans le forum VBA Access
    Réponses: 8
    Dernier message: 08/06/2012, 15h49
  2. Mesure du temps de calcul avec time.clock()
    Par céline80 dans le forum Général Python
    Réponses: 2
    Dernier message: 21/09/2009, 18h02
  3. Mesure de temps avec fork
    Par fab101 dans le forum POSIX
    Réponses: 4
    Dernier message: 30/06/2008, 02h14
  4. mesurer le temps avec precision
    Par xantares dans le forum API, COM et SDKs
    Réponses: 4
    Dernier message: 11/03/2006, 12h22
  5. Mesurer le temps des instructions
    Par luckylucke dans le forum Assembleur
    Réponses: 9
    Dernier message: 03/09/2003, 22h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo