résolution de std:: chrono:: horloge haute résolution ne correspond pas aux mesures
Permettez-moi de poser ma question par ce programme d'essai:
#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:: Cut prend?
std::cout prend 1000200 nanosecondes
je reçois soit 1000200
ou 1000300
ou 1000400
ou 1000500
ou 1000600
ou 2000600
résultat (=1 ou 2 microsecondes). De toute évidence, soit la résolution de std::chrono
est et non 100 nano-secondes ou la façon dont je mesure le temps de std::cout
est erronée. (pourquoi je ne reçois jamais quelque chose entre 1 et 2 microsecondes, par exemple 1500000
?)
j'ai besoin d'un minuteur haute résolution en C++. L'OS lui-même fournit un minuteur à haute résolution parce que je suis capable de mesurer les choses avec une microseconde-précision en utilisant C# Classe Stopwatch
sur la même machine. J'aurais donc juste besoin d'utiliser correctement la minuterie haute résolution du système d'exploitation!
Comment puis-je corriger mon programme pour produire les résultats attendus?
3 réponses
je suppose que vous utilisez VS2012; sinon, ne tenez pas compte de cette réponse. VS2012 typedef
's high_resolution_clock
à system_clock
. Malheureusement, cela signifie qu'il a une précision merdique (environ 1m). J'ai écrit une meilleure horloge haute résolution qui utilise QueryPerformanceCounter
pour une utilisation en 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 #fi pour voir si il est compilé sur 2012 le 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 qui peut être représentée par le type de données que l'horloge utilise. Dans ce cas, votre application utilise un type de données qui peut représenter une durée aussi petit que 100 nanosecondes, mais l'horloge ne possède pas une telle résolution.
la faible résolution du high_resolution_clock
de Visual Studio est un problème depuis plusieurs années. La norme C++ de Microsoft le responsable de la bibliothèque, Stephan T. Lavavej, 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 haute résolution?
il semble que vous utilisez Windows (vous mentionnez C#) donc si vous êtes un timer et que vous utilisez effectivement windows, vous pouvez utiliser QueryPerformanceFrequency et QueryPerformanceCounter .