web-dev-qa-db-fra.com

la résolution de std :: chrono :: high_resolution_clock ne correspond pas aux mesures

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?

30
javapowered

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.

52
David

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

6
bames53

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 .

1
graham.reeds