Permettez-moi de poser ma question par ce programme de test:
#include <iostream>
#include <chrono>
using std::chrono::nanoseconds;
using std::chrono::duration_cast;
int main(int argc, char* argv[])
{
std::cout << "resolution (nano) = " << (double) std::chrono::high_resolution_clock::period::num
/ std::chrono::high_resolution_clock::period::den * 1000 * 1000 * 1000 << std::endl;
auto t1 = std::chrono::high_resolution_clock::now();
std::cout << "how much nanoseconds std::cout takes?" << std::endl;
auto t2 = std::chrono::high_resolution_clock::now();
auto diff = t2-t1;
nanoseconds ns = duration_cast<nanoseconds>(diff);
std::cout << "std::cout takes " << ns.count() << " nanoseconds" << std::endl;
return 0;
}
Sortie sur ma machine:
résolution (nano) = 100
combien de nanosecondes std :: cout prend?
std :: cout prend 1000200 nanosecondes
Je reçois soit 1000200
ou 1000300
ou 1000400
ou 1000500
ou 1000600
ou 2000600
en conséquence (= 1 ou 2 microsecondes). De toute évidence, la résolution de std::chrono
est pas 100 nano-secondes o la façon dont je mesure le temps de std::cout
est faux. (pourquoi je ne reçois jamais quelque chose entre 1 et 2 microsecondes, par exemple 1500000
?)
J'ai besoin d'une minuterie haute résolution en C++. Le système d'exploitation lui-même fournit une minuterie haute résolution car je suis capable de mesurer des choses avec une précision en microsecondes en utilisant la classe C # Stopwatch
sur la même machine. Il me suffirait donc d'utiliser correctement le minuteur haute résolution du système d'exploitation!
Comment corriger mon programme pour produire les résultats attendus?
Je suppose que vous utilisez VS2012; Sinon, ignorez cette réponse. VS2012 typedef
's high_resolution_clock
à system_clock
. Malheureusement, cela signifie qu'il a une précision minable (environ 1 ms). J'ai écrit une meilleure horloge haute résolution qui utilise QueryPerformanceCounter
pour une utilisation dans VS2012 ...
HighResClock.h:
struct HighResClock
{
typedef long long rep;
typedef std::nano period;
typedef std::chrono::duration<rep, period> duration;
typedef std::chrono::time_point<HighResClock> time_point;
static const bool is_steady = true;
static time_point now();
};
HighResClock.cpp:
namespace
{
const long long g_Frequency = []() -> long long
{
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
return frequency.QuadPart;
}();
}
HighResClock::time_point HighResClock::now()
{
LARGE_INTEGER count;
QueryPerformanceCounter(&count);
return time_point(duration(count.QuadPart * static_cast<rep>(period::den) / g_Frequency));
}
(J'ai omis une assertion et #ifs pour voir si elle est compilée en 2012 à partir du code ci-dessus)
Vous pouvez utiliser cette horloge n'importe où et de la même manière que les horloges standard.
La résolution d'une horloge n'est pas nécessairement la même que la plus petite durée pouvant être représentée par le type de données utilisé par l'horloge. Dans ce cas, votre implémentation utilise un type de données qui peut représenter une durée aussi petite que 100 nanosecondes, mais l'horloge sous-jacente n'a pas réellement une telle résolution.
La faible résolution du high_resolution_clock
De Visual Studio pose problème depuis plusieurs années. Stephan T. Lavavej, mainteneur de bibliothèque standard C++ de Microsoft, a indiqué que cela a été corrigé dans VS2015 via l'utilisation de QueryPerformanceCounter()
.
Peut-être que l'implémentation n'implémente pas le minuteur de résolution supérieure?
Il semble que vous utilisez Windows (vous mentionnez C #), donc si vous êtes un minuteur et que vous utilisez en effet des fenêtres, vous pouvez utiliser QueryPerformanceFrequency et QueryPerformanceCounter .