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?

27
demandé sur David 2013-04-30 15:41:15

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.

48
répondu David 2013-04-30 12:09:32

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() .

5
répondu bames53 2015-12-08 17:57:55

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 .

1
répondu graham.reeds 2013-04-30 11:54:13