2013-04-30 12 views
25

Lasciatemi chiedere la mia domanda per questo programma di test:risoluzione std :: :: crono high_resolution_clock non corrisponde alle misure

#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; 
} 

uscita sulla mia macchina:

risoluzione (nano) = 100

quanto nanosecondi std :: cout richiede?

std :: cout richiederà 1000200 nanosecondi

ho ricevuto sia 1000200 o 1000300 o 1000400 o 1000500 o 1000600 o 2000600 come risultato (= 1 o 2 microsecondo). Ovviamente o la risoluzione di std::chrono è non 100 nano-secondi o il modo in cui misuro il tempo di std::cout è errato. (perché non ricevo mai qualcosa tra 1 e 2 microsecondi, ad esempio 1500000?)

Ho bisogno di un timer ad alta risoluzione in C++. Il sistema operativo stesso fornisce un timer ad alta risoluzione perché sono in grado di misurare le cose con precisione al microsecondo utilizzando la classe C# Stopwatch sulla stessa macchina. Quindi avrei solo bisogno di usare correttamente il timer ad alta risoluzione del sistema operativo!

Come posso risolvere il mio programma per produrre i risultati attesi?

+1

Non riesco a rispondere alla domanda, ma per quello che vale, questo codice produce risultati corretti (precisione nanosecondi) sulla mia macchina, quindi il problema è molto probabilmente nella vostra implementazione di libreria. – Mankarse

+0

Correlati: http://stackoverflow.com/questions/8386128/how-to-get-the-precision-of-high-resolution-clock – stefan

+0

Stai usando VS2012? – David

risposta

47

Ho intenzione di indovinare si sta utilizzando VS2012; Altrimenti, ignorare questa risposta. VS2012 typedef 's high_resolution_clock a system_clock. Purtroppo, questo significa che ha una precisione scadente (circa 1 ms). Ho scritto una migliore alta risoluzione orologio che utilizza QueryPerformanceCounter per l'uso in 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)); 
} 

(ho lasciato un assert e #ifs per vedere se è stato compilato nel 2012 dal codice precedente)

Puoi usare questo orologio ovunque e allo stesso modo degli orologi standard.

+0

'VS2012 typedef's high_resolution_clock to system_clock' perché? se voglio ancora usare il timer ad alta risoluzione C++ 11 come posso forzare VS2012 a farlo? – javapowered

+3

@javapowered Lo hanno fatto perché credono di avere troppa quota di mercato e vogliono escludere le persone dall'uso di VS. Visual Studio aspira in diversi modi, questo è uno di questi. Sopra è come high_resolution_clock _should've_ è stato implementato nella libreria standard di VS ... È anche troppo semplice, quindi non so perché sono appena andati e li abbiamo digitati in 'system_clock'. Forse è appena sfuggito alle fessure. – David

+3

È interessante sapere che * L'implementazione VC++ 2012 è stata riconosciuta come un bug dal manutentore della libreria standard di MS *. - (http://stackoverflow.com/questions/13263277/difference-between-stdsystem-clock-and-stdsteady-clock) – SChepurin

1

Forse l'implementazione non implementa il timer con risoluzione più elevata?

Sembra che si stia utilizzando Windows (si parla di C#) quindi se si utilizza un timer e si sta effettivamente utilizzando Windows è possibile utilizzare QueryPerformanceFrequency e QueryPerformanceCounter.

+0

le funzioni QPC sono mappate anche a qualcosa nel namespace std :: chrono? – stijn

+0

@stefan: Qual è la tua fonte su tale richiesta? – interjay

+1

Lo standard dice solo "Gli oggetti di classe high_resolution_clock rappresentano gli orologi con il periodo di tick più breve". Non dice in quale contesto: il mondo, il sistema o l'implementazione. IMO, questo fraseggio significa che nessun altro orologio fornito dall'implementazione potrebbe essere più accurato. In particolare, se system_clock o steady_clock fossero più precisi, ciò non sarebbe valido. Per quanto riguarda cppreference.com, è una wiki modificata dalla comunità e ha un significato normativo zero. –

5

La risoluzione di un orologio non è necessariamente uguale alla durata minima che può essere rappresentata dal tipo di dati utilizzato dall'orologio. In questo caso l'implementazione utilizza un tipo di dati che può rappresentare una durata di soli 100 nanosecondi, ma l'orologio sottostante non ha effettivamente una tale risoluzione.


La bassa risoluzione di Visual Studio di high_resolution_clock è stato un problema per diversi anni. Il manutentore della libreria standard C++ di Microsoft, Stephan T. Lavavej, has indicated, che è stato corretto in VS2015 tramite l'uso di QueryPerformanceCounter().

Problemi correlati