Différence entre STD:: horloge système et std:: horloge stable?
Quelle est la différence entre std::system_clock
et std::steady_clock
? (Un exemple qui illustre des résultats/comportements différents serait génial).
si mon but est de mesurer précisément le temps d'exécution des fonctions (comme un benchmark), quel serait le meilleur choix entre std::system_clock
, std::steady_clock
et std::high_resolution_clock
?
3 réponses
From N3376:
20.11.7.1 [time.horloge.system] / 1:
les Objets de la classe
system_clock
représentent l'horloge du mur de temps de l'ensemble du système en temps réel de l'horloge.
20.11.7.2 [time.horloge.stable] / 1:
les objets de la classe
steady_clock
représentent des horloges pour lesquelles les valeurs detime_point
ne diminuent jamais au fur et à mesure que le temps physique progresse et pour lesquelles les valeurs detime_point
avancer à un rythme régulier par rapport au temps réel. Qui est, l'horloge ne peut pas être ajusté.
20.11.7.3 [time.horloge.embauches] / 1:
les Objets de la classe
high_resolution_clock
représentent les horloges les plus brefs tique période.high_resolution_clock
peut être synonyme desystem_clock
ousteady_clock
.
par exemple, l'horloge du système pourrait être affectée par quelque chose comme la lumière du jour temps d'épargne, à partir duquel l'heure réelle indiquée à un moment donné dans l'avenir peut être en fait un temps dans le passé. (P. ex. aux Etats-Unis, à l'automne le temps recule d'une heure, donc la même heure est vécue "deux fois") cependant, steady_clock
n'est pas autorisé à être affecté par de telles choses.
une autre façon de penser" stable " dans ce cas est dans les exigences définies dans le tableau du 20.11.3 [temps.horloge.demande 2:
Dans Le Tableau 59
C1
etC2
désignent des types d'horloge.t1
ett2
sont des valeurs retournées parC1::now()
où l'appel retournantt1
se produit avant l'appel retournantt2
et ces deux appels se produisent avantC1::time_point::max()
. [ Note: cela signifie queC1
ne s'est pas enroulé entret1
ett2
. -la note de fin ]Expression:
C1::is_steady
Retourne:const bool
Sémantique opérationnelle:true
sit1 <= t2
est toujours vrai et le temps entre les tiques d'horloge est constant, sinonfalse
.
C'est la norme sur leurs différences.
si vous voulez faire du benchmarking, votre meilleur pari sera probablement std::high_resolution_clock
, car il est probable que votre plate-forme utilise une minuterie haute résolution (par exemple QueryPerformanceCounter
sur Windows) pour ceci horloge. Cependant, si vous faites de l'analyse comparative, vous devriez vraiment envisager d'utiliser des minuteries spécifiques à la plate-forme pour votre benchmark, parce que différentes plates-formes gèrent cela différemment. Par exemple, certaines plates-formes peuvent vous donner des moyens de déterminer le nombre réel de temps nécessaire au programme (indépendamment d'autres processus tournant sur le même CPU). Mieux encore, mettez la main sur un vrai profileur et utilisez ça.
Billy a fourni une excellente réponse basée sur la norme ISO C++ avec laquelle je suis entièrement d'accord. Cependant, il y a un autre aspect de l'histoire - la vie réelle. Il semble qu'en ce moment il n'y a vraiment aucune différence entre ces horloges dans la mise en œuvre de compilateurs populaires:
gcc 4.8:
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
...
#else
typedef system_clock steady_clock;
#endif
typedef system_clock high_resolution_clock;
Visual Studio 2012:
class steady_clock : public system_clock
{ // wraps monotonic clock
public:
static const bool is_monotonic = true; // retained
static const bool is_steady = true;
};
typedef system_clock high_resolution_clock;
dans le cas de gcc vous pouvez vérifier si vous avez affaire à l'horloge stable simplement en vérifiant is_steady
et se comporter en conséquence. Cependant VS2012 semble tricher un peu ici : -)
si vous avez besoin d'horloge de haute précision, je vous recommande pour l'instant d'écrire votre propre horloge qui est conforme à l'interface d'horloge officielle C++11 et d'attendre les implémentations pour rattraper. Ce sera une approche bien meilleure que d'utiliser L'API spécifique au système D'exploitation directement dans votre code. Pour Windows vous pouvez le faire comme cela:
// Self-made Windows QueryPerformanceCounter based C++11 API compatible clock
struct qpc_clock {
typedef std::chrono::nanoseconds duration; // nanoseconds resolution
typedef duration::rep rep;
typedef duration::period period;
typedef std::chrono::time_point<qpc_clock, duration> time_point;
static bool is_steady; // = true
static time_point now()
{
if(!is_inited) {
init();
is_inited = true;
}
LARGE_INTEGER counter;
QueryPerformanceCounter(&counter);
return time_point(duration(static_cast<rep>((double)counter.QuadPart / frequency.QuadPart *
period::den / period::num)));
}
private:
static bool is_inited; // = false
static LARGE_INTEGER frequency;
static void init()
{
if(QueryPerformanceFrequency(&frequency) == 0)
throw std::logic_error("QueryPerformanceCounter not supported: " + std::to_string(GetLastError()));
}
};
Pour Linux c'est encore plus facile. Il suffit de lire la page de manuel de clock_gettime
et modifier le code ci-dessus.
GCC 5.3.0 mise en œuvre
C++ stdlib est à l'intérieur de source de GCC:
-
high_resolution_clock
est un alias poursystem_clock
-
system_clock
transmet au premier des suivants qui est disponible:-
clock_gettime(CLOCK_REALTIME, ...)
-
gettimeofday
-
time
-
-
steady_clock
transmet au premier des suivants qui est disponible:-
clock_gettime(CLOCK_MONOTONIC, ...)
-
system_clock
-
puis CLOCK_REALTIME
vs CLOCK_MONOTONIC
s'explique à: différence entre CLOCK_REALTIME et CLOCK_MONOTONIC?