115 votes

Différence entre std::system_clock et std::steady_clock ?

Quelle est la différence entre std::system_clock y std::steady_clock ? (Un exemple de cas illustrant des résultats/comportements différents serait formidable).

Si mon objectif 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 y std::high_resolution_clock ?

82voto

Billy ONeal Points 50631

De N3376 :

20.11.7.1 [time.clock.system]/1:

Objets de la classe system_clock représente l'heure de l'horloge murale de l'horloge en temps réel du système.

20.11.7.2 [time.clock.steady]/1:

Objets de la classe steady_clock représentent des horloges pour lesquelles les valeurs de time_point ne diminuent jamais lorsque le temps physique avance et pour lesquelles les valeurs de time_point avancer à un rythme régulier par rapport au temps réel. Autrement dit, l'horloge ne peut pas être réglée.

20.11.7.3 [time.clock.hires]/1:

Objets de la classe high_resolution_clock représentent les horloges dont la période de tic-tac est la plus courte. high_resolution_clock peut être un synonyme de system_clock o steady_clock .

Par exemple, l'horloge du système peut être affectée par quelque chose comme l'heure d'été, auquel cas l'heure réelle indiquée à un moment donné dans le futur peut en fait être une heure dans le passé. (Par exemple, aux États-Unis, à l'automne, le temps recule d'une heure, de sorte que la même heure est vécue "deux fois"), steady_clock n'est pas autorisé à être affecté par de telles choses.

Une autre façon de penser à la "stabilité" dans ce cas est dans les exigences définies dans le tableau de 20.11.3 [time.clock.req]/2 :

Dans le tableau 59 C1 y C2 désignent les types d'horloge. t1 y t2 sont des valeurs renvoyées par C1::now() où l'appel retournant t1 se produit avant l'appel retournant t2 et ces deux appels ont lieu avant C1::time_point::max() . [Note : cela signifie C1 ne s'est pas enroulé entre t1 y t2 . -note finale ]

Expression : C1::is_steady
Les retours : const bool
Sémantique opérationnelle : true si t1 <= t2 est toujours vrai et le temps entre les ticks de l'horloge est constant, sinon false .

C'est tout ce que la norme a sur leurs différences.

Si vous voulez faire de l'analyse comparative, votre meilleur choix sera probablement std::high_resolution_clock car il est probable que votre plate-forme utilise une minuterie à haute résolution (par exemple, la minuterie de l'ordinateur). QueryPerformanceCounter sur Windows) pour cette horloge. Cependant, si vous effectuez un benchmarking, vous devriez vraiment envisager d'utiliser des horloges spécifiques à la plateforme pour votre benchmark, car les différentes plateformes gèrent cela différemment. Par exemple, certaines plates-formes peuvent vous donner des moyens de déterminer le nombre réel de ticks d'horloge requis par le programme (indépendamment des autres processus exécutés sur le même processeur). Mieux encore, mettez la main sur un vrai profileur et utilisez-le.

52voto

Mateusz Pusz Points 725

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'à l'heure actuelle, il n'y ait pas vraiment de différence entre ces horloges dans la mise en œuvre des 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 à une 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'une horloge de haute précision, je vous recommande pour l'instant d'écrire votre propre horloge conforme à l'interface officielle C++11 et d'attendre que les implémentations rattrapent leur retard. Ce sera une bien meilleure approche que d'utiliser l'API spécifique du système d'exploitation directement dans votre code. Pour Windows, vous pouvez procéder de la sorte :

// 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 modifiez le code ci-dessus.

26voto

Ciro Santilli Points 3341

Mise en œuvre de GCC 5.3.0

C++ stdlib est dans les sources de GCC :

  • high_resolution_clock est un alias pour system_clock
  • system_clock en avant vers le premier des suivants qui est disponible :
    • clock_gettime(CLOCK_REALTIME, ...)
    • gettimeofday
    • time
  • steady_clock en avant vers le premier des suivants qui est disponible :
    • clock_gettime(CLOCK_MONOTONIC, ...)
    • system_clock

Puis CLOCK_REALTIME vs CLOCK_MONOTONIC est expliqué à l'adresse suivante Différence entre CLOCK_REALTIME et CLOCK_MONOTONIC ?

7voto

Adria Points 51

Discussion pertinente sur le chrono par Howard Hinnant , auteur de chrono :

n'utilisez pas high_resolution_clock car il s'agit d'un alias pour l'un d'entre eux :

  • system_clock Il s'agit d'une horloge normale, à utiliser pour les questions relatives à l'heure et à la date.
  • steady_clock : c'est comme un chronomètre, utilisez-le pour chronométrer des choses.

6voto

Silviu Points 18

Peut-être que la différence la plus significative est le fait que le point de départ de l'étude de l std::chrono:system_clock est l'époque 1.1.1970, dite époque UNIX. De l'autre côté, pour std::chrono::steady_clock typiquement le temps de démarrage de votre PC et il est le plus approprié pour mesurer les intervalles.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X