J'essaie d'utiliser time () pour mesurer différents points de mon programme.
Ce que je ne comprends pas, c'est pourquoi les valeurs d'avant et d'après sont les mêmes? Je comprends que ce n’est pas la meilleure façon de profiler mon programme, je veux juste voir combien de temps cela prend.
printf("**MyProgram::before time= %ld\n", time(NULL));
doSomthing();
doSomthingLong();
printf("**MyProgram::after time= %ld\n", time(NULL));
J'ai essayé:
struct timeval diff, startTV, endTV;
gettimeofday(&startTV, NULL);
doSomething();
doSomethingLong();
gettimeofday(&endTV, NULL);
timersub(&endTV, &startTV, &diff);
printf("**time taken = %ld %ld\n", diff.tv_sec, diff.tv_usec);
Comment lire le résultat de **time taken = 0 26339
? Cela signifie-t-il 26 339 nanosecondes = 26,3 ms?
Qu'en est-il de **time taken = 4 45025
, cela signifie-t-il 4 secondes et 25 ms?
_#include <ctime>
void f() {
using namespace std;
clock_t begin = clock();
code_to_time();
clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
}
_
La fonction time()
n'a qu'une précision d'une seconde à la fois, mais il existe CLOCKS_PER_SEC
"horloges" à une seconde près. Il s'agit d'une mesure facile et portable, même si elle est simplifiée à l'excès.
Vous pouvez abstraire le mécanisme de mesure du temps et faire mesurer le temps d'exécution de chaque appelable avec un code supplémentaire minimal , simplement en étant appelé via une structure de minuterie. De plus, au moment de la compilation, vous pouvez paramétrer le type de minutage (millisecondes, nanosecondes, etc.).
Merci à la révision de Loki Astari et à la suggestion d'utiliser des modèles variadiques.This est pourquoi l'appel de fonction transféré.
_#include <iostream>
#include <chrono>
template<typename TimeT = std::chrono::milliseconds>
struct measure
{
template<typename F, typename ...Args>
static typename TimeT::rep execution(F&& func, Args&&... args)
{
auto start = std::chrono::steady_clock::now();
std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
auto duration = std::chrono::duration_cast< TimeT>
(std::chrono::steady_clock::now() - start);
return duration.count();
}
};
int main() {
std::cout << measure<>::execution(functor(dummy)) << std::endl;
}
_
Selon le commentaire de Howard Hinnant , il vaut mieux ne pas s'échapper du système de chrono avant de devoir le faire. La classe ci-dessus pourrait donc donner à l'utilisateur le choix d'appeler count
manuellement en fournissant une méthode statique supplémentaire (illustrée en C++ 14).
_template<typename F, typename ...Args>
static auto duration(F&& func, Args&&... args)
{
auto start = std::chrono::steady_clock::now();
std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
return std::chrono::duration_cast<TimeT>(std::chrono::steady_clock::now()-start);
}
// call .count() manually later when needed (eg IO)
auto avg = (measure<>::duration(func) + measure<>::duration(func)) / 2.0;
_
et être le plus utile pour les clients qui
"vouloir post-traiter un tas de durées avant l'entrée/sortie (par exemple, la moyenne)"
Le code complet peut être trouvé ici . Ma tentative de construire un outil d'analyse comparative basé sur le chrono est enregistrée ici .
Si std::invoke
est disponible dans C++ 17, l'appel de l'appelable dans execution
pourrait être effectué de la manière suivante:
_invoke(forward<decltype(func)>(func), forward<Args>(args)...);
_
pour fournir des callables qui sont des pointeurs vers des fonctions membres.
//***C++11 Style:***
#include <chrono>
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "[µs]" << std::endl;
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::nanoseconds> (end - begin).count() << "[ns]" << std::endl;
Comme vous pouvez le constater d'après votre question, il semble que vous souhaitiez connaître le temps écoulé après l'exécution d'un morceau de code. Je suppose que vous seriez à l'aise de voir les résultats en seconde (s). Si c'est le cas, essayez d'utiliser la fonction difftime()
comme indiqué ci-dessous. J'espère que ceci résoudra votre problème.
#include <time.h>
#include <stdio.h>
time_t start,end;
time (&start);
.
.
.
<your code>
.
.
.
time (&end);
double dif = difftime (end,start);
printf ("Elasped time is %.2lf seconds.", dif );
Windows uniquement: (La balise Linux a été ajoutée après que j'ai posté cette réponse)
Vous pouvez utiliser GetTickCount () pour obtenir le nombre de millisecondes écoulées depuis le démarrage du système.
long int before = GetTickCount();
// Perform time-consuming operation
long int after = GetTickCount();
la fonction time (NULL) renvoie le nombre de secondes écoulées depuis le 01/01/1970 à 00:00. Et comme cette fonction est appelée à un moment différent dans votre programme, elle sera toujours différente Time in C++
time(NULL)
renvoie le nombre de secondes écoulées depuis le 01/01/1970 à 00:00 ( the Epoch ). La différence entre les deux valeurs correspond donc au nombre de secondes que votre traitement a pris.
int t0 = time(NULL);
doSomthing();
doSomthingLong();
int t1 = time(NULL);
printf ("time = %d secs\n", t1 - t0);
Vous pouvez obtenir des résultats plus précis avec getttimeofday()
, qui renvoie l'heure actuelle en secondes, comme time()
, ainsi qu'en microsecondes.
struct profiler
{
std::string name;
std::chrono::high_resolution_clock::time_point p;
profiler(std::string const &n) :
name(n), p(std::chrono::high_resolution_clock::now()) { }
~profiler()
{
using dura = std::chrono::duration<double>;
auto d = std::chrono::high_resolution_clock::now() - p;
std::cout << name << ": "
<< std::chrono::duration_cast<dura>(d).count()
<< std::endl;
}
};
#define PROFILE_BLOCK(pbn) profiler _pfinstance(pbn)
L'utilisation est ci-dessous ::
{
PROFILE_BLOCK("Some time");
// your code or function
}
Ceci est similaire à RAII dans la portée
NOTE ce n'est pas le mien, mais je pensais que c'était pertinent ici
#include<time.h> // for clock
#include<math.h> // for fmod
#include<cstdlib> //for system
#include <stdio.h> //for delay
using namespace std;
int main()
{
clock_t t1,t2;
t1=clock(); // first time capture
// Now your time spanning loop or code goes here
// i am first trying to display time elapsed every time loop runs
int ddays=0; // d prefix is just to say that this variable will be used for display
int dhh=0;
int dmm=0;
int dss=0;
int loopcount = 1000 ; // just for demo your loop will be different of course
for(float count=1;count<loopcount;count++)
{
t2=clock(); // we get the time now
float difference= (((float)t2)-((float)t1)); // gives the time elapsed since t1 in milliseconds
// now get the time elapsed in seconds
float seconds = difference/1000; // float value of seconds
if (seconds<(60*60*24)) // a day is not over
{
dss = fmod(seconds,60); // the remainder is seconds to be displayed
float minutes= seconds/60; // the total minutes in float
dmm= fmod(minutes,60); // the remainder are minutes to be displayed
float hours= minutes/60; // the total hours in float
dhh= hours; // the hours to be displayed
ddays=0;
}
else // we have reached the counting of days
{
float days = seconds/(24*60*60);
ddays = (int)(days);
float minutes= seconds/60; // the total minutes in float
dmm= fmod(minutes,60); // the rmainder are minutes to be displayed
float hours= minutes/60; // the total hours in float
dhh= fmod (hours,24); // the hours to be displayed
}
cout<<"Count Is : "<<count<<"Time Elapsed : "<<ddays<<" Days "<<dhh<<" hrs "<<dmm<<" mins "<<dss<<" secs";
// the actual working code here,I have just put a delay function
delay(1000);
system("cls");
} // end for loop
}// end of main
Les valeurs imprimées par votre deuxième programme sont secondes et microsecondes.
0 26339 = 0.026'339 s = 26339 µs
4 45025 = 4.045'025 s = 4045025 µs
#include <ctime>
#include <cstdio>
#include <iostream>
#include <chrono>
#include <sys/time.h>
using namespace std;
using namespace std::chrono;
void f1()
{
high_resolution_clock::time_point t1 = high_resolution_clock::now();
high_resolution_clock::time_point t2 = high_resolution_clock::now();
double dif = duration_cast<nanoseconds>( t2 - t1 ).count();
printf ("Elasped time is %lf nanoseconds.\n", dif );
}
void f2()
{
timespec ts1,ts2;
clock_gettime(CLOCK_REALTIME, &ts1);
clock_gettime(CLOCK_REALTIME, &ts2);
double dif = double( ts2.tv_nsec - ts1.tv_nsec );
printf ("Elasped time is %lf nanoseconds.\n", dif );
}
void f3()
{
struct timeval t1,t0;
gettimeofday(&t0, 0);
gettimeofday(&t1, 0);
double dif = double( (t1.tv_usec-t0.tv_usec)*1000);
printf ("Elasped time is %lf nanoseconds.\n", dif );
}
void f4()
{
high_resolution_clock::time_point t1 , t2;
double diff = 0;
t1 = high_resolution_clock::now() ;
for(int i = 1; i <= 10 ; i++)
{
t2 = high_resolution_clock::now() ;
diff+= duration_cast<nanoseconds>( t2 - t1 ).count();
t1 = t2;
}
printf ("high_resolution_clock:: Elasped time is %lf nanoseconds.\n", diff/10 );
}
void f5()
{
timespec ts1,ts2;
double diff = 0;
clock_gettime(CLOCK_REALTIME, &ts1);
for(int i = 1; i <= 10 ; i++)
{
clock_gettime(CLOCK_REALTIME, &ts2);
diff+= double( ts2.tv_nsec - ts1.tv_nsec );
ts1 = ts2;
}
printf ("clock_gettime:: Elasped time is %lf nanoseconds.\n", diff/10 );
}
void f6()
{
struct timeval t1,t2;
double diff = 0;
gettimeofday(&t1, 0);
for(int i = 1; i <= 10 ; i++)
{
gettimeofday(&t2, 0);
diff+= double( (t2.tv_usec-t1.tv_usec)*1000);
t1 = t2;
}
printf ("gettimeofday:: Elasped time is %lf nanoseconds.\n", diff/10 );
}
int main()
{
// f1();
// f2();
// f3();
f6();
f4();
f5();
return 0;
}
C++ std :: chrono présente l'avantage d'être multiplate-forme. Cependant, il introduit également une surcharge importante par rapport à POSIX clock_gettime (). Sur ma machine Linux, tous les types std::chrono::xxx_clock::now()
fonctionnent à peu près de la même manière:
std::chrono::system_clock::now()
std::chrono::steady_clock::now()
std::chrono::high_resolution_clock::now()
Bien que POSIX clock_gettime(CLOCK_MONOTONIC, &time)
devrait être identique à steady_clock::now()
, il est plus de x3 fois plus rapide!
Voici mon test, pour être complet.
#include <stdio.h>
#include <chrono>
#include <ctime>
void print_timediff(const char* prefix, const struct timespec& start, const
struct timespec& end)
{
double milliseconds = end.tv_nsec >= start.tv_nsec
? (end.tv_nsec - start.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec) * 1e3
: (start.tv_nsec - end.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec - 1) * 1e3;
printf("%s: %lf milliseconds\n", prefix, milliseconds);
}
int main()
{
int i, n = 1000000;
struct timespec start, end;
// Test stopwatch
clock_gettime(CLOCK_MONOTONIC, &start);
for (i = 0; i < n; ++i) {
struct timespec dummy;
clock_gettime(CLOCK_MONOTONIC, &dummy);
}
clock_gettime(CLOCK_MONOTONIC, &end);
print_timediff("clock_gettime", start, end);
// Test chrono system_clock
clock_gettime(CLOCK_MONOTONIC, &start);
for (i = 0; i < n; ++i)
auto dummy = std::chrono::system_clock::now();
clock_gettime(CLOCK_MONOTONIC, &end);
print_timediff("chrono::system_clock::now", start, end);
// Test chrono steady_clock
clock_gettime(CLOCK_MONOTONIC, &start);
for (i = 0; i < n; ++i)
auto dummy = std::chrono::steady_clock::now();
clock_gettime(CLOCK_MONOTONIC, &end);
print_timediff("chrono::steady_clock::now", start, end);
// Test chrono high_resolution_clock
clock_gettime(CLOCK_MONOTONIC, &start);
for (i = 0; i < n; ++i)
auto dummy = std::chrono::high_resolution_clock::now();
clock_gettime(CLOCK_MONOTONIC, &end);
print_timediff("chrono::high_resolution_clock::now", start, end);
return 0;
}
Et voici le résultat obtenu lors de la compilation avec gcc7.2 -O3:
clock_gettime: 24.484926 milliseconds
chrono::system_clock::now: 85.142108 milliseconds
chrono::steady_clock::now: 87.295347 milliseconds
chrono::high_resolution_clock::now: 84.437838 milliseconds
L'appel à la fonction time(NULL)
renverra le nombre de secondes écoulées depuis l'époque: le 1er janvier 1970. Vous voulez peut-être faire la différence entre deux horodatages:
size_t start = time(NULL);
doSomthing();
doSomthingLong();
printf ("**MyProgram::time elapsed= %lds\n", time(NULL) - start);
Je devais mesurer le temps d'exécution de chaque fonction dans une bibliothèque. Je ne voulais pas avoir à encapsuler chaque appel de chaque fonction avec une fonction de mesure du temps, car cela est moche et approfondit la pile d'appels. Je ne voulais pas non plus mettre le code du minuteur en haut et en bas de chaque fonction, car cela crée un désordre lorsque la fonction peut quitter tôt ou émettre des exceptions, par exemple. Donc, ce que j'ai fini par faire était de créer une minuterie qui utilise sa propre durée de vie pour mesurer le temps.
De cette façon, je peux mesurer le temps passé par un bloc de code en instanciant simplement l'un de ces objets au début du bloc de code en question (fonction ou toute autre étendue) et en permettant ensuite au destructeur d'instances de mesurer le temps écoulé depuis. construction lorsque l'instance sort du cadre. Vous pouvez trouver l'exemple complet ici mais la structure est extrêmement simple:
template <typename clock_t = std::chrono::steady_clock>
struct scoped_timer {
using duration_t = typename clock_t::duration;
const std::function<void(const duration_t&)> callback;
const std::chrono::time_point<clock_t> start;
scoped_timer(const std::function<void(const duration_t&)>& finished_callback) :
callback(finished_callback), start(clock_t::now()) { }
scoped_timer(std::function<void(const duration_t&)>&& finished_callback) :
callback(finished_callback), start(clock_t::now()) { }
~scoped_timer() { callback(clock_t::now() - start); }
};
La structure vous rappellera sur le foncteur fourni quand il sera hors de portée afin que vous puissiez faire quelque chose avec les informations de minutage (les imprimer ou les stocker ou autre). Si vous devez faire quelque chose d'encore plus complexe, vous pouvez même utiliser std::bind
avec std::placeholders
pour rappeler des fonctions avec plus d'arguments.
Voici un exemple rapide d'utilisation:
void test(bool should_throw) {
scoped_timer<> t([](const scoped_timer<>::duration_t& elapsed) {
auto e = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(elapsed).count();
std::cout << "took " << e << "ms" << std::endl;
});
std::this_thread::sleep_for(std::chrono::seconds(1));
if (should_throw)
throw nullptr;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
Si vous voulez être plus volontaire, vous pouvez également utiliser new
et delete
pour lancer et arrêter explicitement le chronomètre sans vous fier à la portée pour le faire à votre place.
De ce que nous voyons, tv_sec stocke les secondes écoulées, tandis que tv_usec stocke les microsecondes écoulées séparément. Et ils ne sont pas les conversions les uns des autres. Par conséquent, ils doivent être changés en unité appropriée et ajoutés pour obtenir le temps total écoulé.
struct timeval startTV, endTV;
gettimeofday(&startTV, NULL);
doSomething();
doSomethingLong();
gettimeofday(&endTV, NULL);
printf("**time taken in microseconds = %ld\n",
(endTV.tv_sec * 1e6 + endTV.tv_usec - (startTV.tv_sec * 1e6 + startTV.tv_usec))
);
En interne, la fonction accède à l'horloge du système. C'est pourquoi elle renvoie différentes valeurs à chaque appel. En général, avec des langages non fonctionnels, il peut y avoir de nombreux effets secondaires et états cachés dans des fonctions que vous ne pouvez pas voir en regardant simplement le nom de la fonction et ses arguments.
Sur linux, clock_gettime () est l’un des bons choix. Vous devez lier la bibliothèque en temps réel (-lrt).
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#define BILLION 1000000000L;
int main( int argc, char **argv )
{
struct timespec start, stop;
double accum;
if( clock_gettime( CLOCK_REALTIME, &start) == -1 ) {
perror( "clock gettime" );
exit( EXIT_FAILURE );
}
system( argv[1] );
if( clock_gettime( CLOCK_REALTIME, &stop) == -1 ) {
perror( "clock gettime" );
exit( EXIT_FAILURE );
}
accum = ( stop.tv_sec - start.tv_sec )
+ ( stop.tv_nsec - start.tv_nsec )
/ BILLION;
printf( "%lf\n", accum );
return( EXIT_SUCCESS );
}
Comme d'autres l'ont déjà noté, la fonction time () de la bibliothèque standard C n'a pas une résolution supérieure à une seconde. Clock () est la seule fonction C entièrement portable pouvant offrir une meilleure résolution. Elle mesure le temps processeur, plutôt que le temps wallclock. Si l’on se contente de se limiter aux plates-formes POSIX (Linux, par exemple), la fonction clock_gettime () est un bon choix.
Depuis C++ 11, il existe de bien meilleures installations de chronométrage offrant une meilleure résolution sous une forme qui devrait être très portable entre différents compilateurs et systèmes d'exploitation. De même, la bibliothèque boost :: datetime fournit de bonnes classes de minutage haute résolution qui devraient être très portables.
L’un des problèmes que pose l’utilisation de l’une de ces fonctionnalités est le délai introduit par l’interrogation de l’horloge système. En expérimentant avec clock_gettime (), boost :: datetime et std :: chrono, ce délai peut facilement prendre quelques microsecondes. Ainsi, lorsque vous mesurez la durée d'une partie de votre code, vous devez tenir compte d'une erreur de mesure d'environ cette taille ou tenter de corriger cette erreur zéro d'une manière ou d'une autre. Dans l’idéal, vous souhaiterez peut-être rassembler plusieurs mesures du temps pris par votre fonction et calculer le temps moyen, maximum ou minimum, sur de nombreux cycles.
Pour résoudre tous ces problèmes de portabilité et de collecte de statistiques, j'ai développé la bibliothèque cxx-rtimers disponible sur Github qui tente de fournir une API simple. pour les blocs de chronométrage de code C++, le calcul de zéro erreur et la génération de rapports de statistiques provenant de plusieurs minuteries intégrées dans votre code. Si vous avez un compilateur C++ 11, vous devez simplement #include <rtimers/cxx11.hpp>
et utiliser quelque chose comme:
void expensiveFunction() {
static rtimers::cxx11::DefaultTimer timer("expensiveFunc");
auto scopedStartStop = timer.scopedStart();
// Do something costly...
}
À la sortie du programme, vous obtiendrez un résumé des statistiques de synchronisation écrites dans std :: cerr, telles que:
Timer(expensiveFunc): <t> = 6.65289us, std = 3.91685us, 3.842us <= t <= 63.257us (n=731)
qui indique le temps moyen, son écart type, les limites supérieure et inférieure et le nombre de fois où cette fonction a été appelée.
Si vous souhaitez utiliser des fonctions de minutage spécifiques à Linux, vous pouvez #include <rtimers/posix.hpp>
, ou si vous avez les bibliothèques Boost mais un compilateur C++ plus ancien, vous pouvez #include <rtimers/boost.hpp>
. Il existe également des versions de ces classes de minuteur qui peuvent collecter des informations statistiques de minutage sur plusieurs threads. Il existe également des méthodes vous permettant d'estimer l'erreur zéro associée à deux requêtes immédiatement consécutives de l'horloge système.
J'utilise habituellement ce qui suit:
#include <chrono>
#include <type_traits>
using perf_clock = std::conditional<
std::chrono::high_resolution_clock::is_steady,
std::chrono::high_resolution_clock,
std::chrono::steady_clock
>::type;
using floating_seconds = std::chrono::duration<double>;
template<class F, class... Args>
floating_seconds run_test(Func&& func, Args&&... args)
{
const auto t0 = perf_clock::now();
std::forward<Func>(func)(std::forward<Args>(args)...);
return floating_seconds(perf_clock::now() - t0);
}
C'est la même chose que celle proposée par @ nikos-athanasiou, sauf que j'évite d'utiliser une horloge non stable et d'utiliser un nombre flottant de secondes comme durée.
Ils sont les mêmes parce que votre fonction "Quelque chose se passe plus vite que la granularité de la minuterie". Essayer:
printf ("**MyProgram::before time= %ld\n", time(NULL));
for(i = 0; i < 1000; ++i) {
doSomthing();
doSomthingLong();
}
printf ("**MyProgram::after time= %ld\n", time(NULL));
La raison pour laquelle les deux valeurs sont identiques est que votre procédure longue ne prend pas autant de temps - moins d'une seconde. Vous pouvez simplement ajouter une longue boucle (pour (int i = 0; i <100000000; i ++);) à la fin de la fonction pour vous assurer que c'est bien le problème, nous pourrons ensuite partir de là ...
Au cas où ce qui précède se révèle être vrai, vous devrez trouver une fonction système différente (je comprends que vous travaillez sous Linux, je ne peux donc pas vous aider avec le nom de la fonction) pour mesurer le temps plus précisément. Je suis sûr qu'il existe une fonction similaire à GetTickCount () dans Linux, il vous suffit de la trouver.
En réponse aux OP trois questions spécifiques.
"Ce que je ne comprends pas, c'est pourquoi les valeurs d'avant et d'après sont identiques? "
La première question et l'exemple de code montrent que time()
a une résolution de 1 seconde. La réponse doit donc être que les deux fonctions s'exécutent en moins de 1 seconde. Mais il informera parfois (apparemment illogiquement) 1 seconde si les deux marques de minuterie chevauchent une limite d'une seconde.
L'exemple suivant utilise gettimeofday()
qui remplit cette structure
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
et la deuxième question demande: "Comment lire un résultat de **time taken = 0 26339
? Est-ce que cela signifie 26 339 nanosecondes = 26,3 msec?"
Ma deuxième réponse est que le temps pris est de 0 seconde et 26339 microsecondes, soit 0,026339 seconde, ce qui confirme le premier exemple s’exécutant en moins d’une seconde.
La troisième question demande: "Qu'en est-il de **time taken = 4 45025
, cela signifie-t-il 4 secondes et 25 ms?"
Ma troisième réponse est que le temps pris est de 4 secondes et 45025 microsecondes, soit 4,045025 secondes, ce qui montre que OP a modifié les tâches exécutées par les deux fonctions qu'il a précédemment chronométrées.