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 ?

73
demandé sur 5gon12eder 2012-11-07 08:48:41

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 de time_point ne diminuent jamais au fur et à mesure que le temps physique progresse et pour lesquelles les valeurs de time_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 de system_clock ou steady_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 et C2 désignent des types d'horloge. t1 et t2 sont des valeurs retournées par C1::now() où l'appel retournant t1 se produit avant l'appel retournant t2 et ces deux appels se produisent avant C1::time_point::max() . [ Note: cela signifie que C1 ne s'est pas enroulé entre t1 et t2 . -la note de fin ]

Expression: C1::is_steady

Retourne: const bool

Sémantique opérationnelle: true si t1 <= t2 est toujours vrai et le temps entre les tiques d'horloge est constant, sinon false .

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.

55
répondu Billy ONeal 2018-02-22 07:42:52

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.

42
répondu Mateusz Pusz 2012-11-07 09:13:17

GCC 5.3.0 mise en œuvre

C++ stdlib est à l'intérieur de source de GCC:

  • high_resolution_clock est un alias pour system_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?

11