2016-04-18 8 views
3

Ich habe eine Anwendung, wo ich die MinGW-Implementierung von gettimeofday zu erreichen "präzise" Timing (~ 1ms Präzision) auf Win7. Es funktioniert gut.Timer Unterschiede zwischen Win7 & Win10

Wenn jedoch der gleiche Code (und sogar die gleiche * .exe) auf Win10 verwendet wird, fällt die Genauigkeit drastisch auf die berühmte 15,6 ms Genauigkeit, was für mich nicht genug ist.

Zwei Fragen: - wissen Sie, was die Wurzel für solche Diskrepanzen sein kann? (Ist es eine OS-Konfiguration/"Funktionen"?) - wie kann ich es beheben? Oder gibt es einen präzisen Timer, der von der OS-Konfiguration unabhängig ist?

NB: std::chrono::high_resolution_clock scheint das gleiche Problem zu haben (zumindest zeigt es die 15.6ms Grenze auf Win10).

+2

15.6 ist der normale Wert, es ist Ihre Win7-Installation, die sich schlecht benahm. Rufen Sie timeBeginPeriod() auf oder verwenden Sie QueryPerformanceCounter(), um eine Auflösung unter einer Mikrosekunde zu erhalten. QPF ist am besten. –

+0

Wie kann ein "Fehlverhalten" besser sein? Kommt das von einer Konfigurationsoption? – cyrobin

+1

Normal und "besser" haben gegnerische Ziele. Es ist rauh auf den Stromverbrauch, Sie werden eine Laptop-Batterie in Eile entleeren. Keine Konfiguration, normalerweise ein Programm oder Treiber, der timeBeginPeriod() aufruft. [Chrome ist dafür berüchtigt] (http: //blog.codinghorror.com/warum-hat-windows-haben-schrecklich-batterieleben /). Führen Sie powercfg -energy aus, um den Störenfried auf Win7 zu finden. –

Antwort

1

Von Hans Passant Kommentare und zusätzliche Tests auf meiner Seite, hier ist eine solidere Antwort:

Die 15.6ms (1/64 Sekunde) Grenze ist well-known unter Windows und ist das Standardverhalten. Es ist möglich, den Grenzwert (z. B. auf 1 ms durch einen Anruf auf timeBeginPeriod()) zu senken, obwohl dies nicht empfohlen wird, da dies die globale System-Timer-Auflösung und die resultierende power consumption betrifft. Zum Beispiel Chrome is notorious for doing this‌​. Aufgrund des globalen Aspekts der Zeitgeberauflösung kann daher aufgrund von Programmen von Drittanbietern eine Genauigkeit von 1 ms beobachtet werden, ohne explizit darum zu bitten.

sein Außerdem beachten Sie, dass std::chrono::high_resolution_clock tut nicht auf Windows ein gültiges Verhalten haben (beide in Visual Studio oder MinGW Kontext). Sie können also nicht erwarten, dass diese Schnittstelle eine plattformübergreifende Lösung ist, und das 15.625ms-Limit gilt immer noch.

Wissen, wie können wir damit umgehen? Nun, man kann die timeBeginPeriod() Sache verwenden, um die Genauigkeit einiger Timer zu erhöhen, aber wiederum sind wir nicht dazu raten: es scheint besser zu verwenden QueryPerformanceCounter() (QPC), das ist die primäre API für nativen Code freut sich auf acquire high-resolution time stamps or measure time intervals laut Microsoft. Beachten Sie, dass GPC does count elapsed time (and not CPU cycles). Hier ist ein Anwendungsbeispiel:

LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds; 
LARGE_INTEGER Frequency; 

QueryPerformanceFrequency(&Frequency); 
QueryPerformanceCounter(&StartingTime); 

// Activity to be timed 

QueryPerformanceCounter(&EndingTime); 
ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart; 


// 
// We now have the elapsed number of ticks, along with the 
// number of ticks-per-second. We use these values 
// to convert to the number of elapsed microseconds. 
// To guard against loss-of-precision, we convert 
// to microseconds *before* dividing by ticks-per-second. 
// 

ElapsedMicroseconds.QuadPart *= 1000000; 
ElapsedMicroseconds.QuadPart /= Frequency.QuadPart; 

Nach Microsoft, QPC ist auch geeignet, in einem Multi-Core/Multi-Thread-Kontext, obwohl es weniger präzise sein kann/zweideutig:

Wenn Sie Leistungsindikatoren Ergebnisse vergleichen, die werden von verschiedenen Threads bezogen, berücksichtigen Sie Werte, die sich um ± 1 Tick unterscheiden, um eine mehrdeutige Ordnung zu haben. Wenn die Zeitstempel aus demselben Thread stammen, gilt diese Unsicherheit von ± 1 Tick nicht. In diesem Zusammenhang bezieht sich der Ausdruck Tick auf eine Zeitperiode gleich 1 ÷ (die Frequenz des Leistungszählers, erhalten von QueryPerformanceFrequency).

Als zusätzliche Ressourcen, MS stellt auch eine FAQ on how/why use QPC und eine Erklärung auf clock/timing in Windows.