106 Stimmen

Ist garantiert, dass gettimeofday() eine Auflösung von Mikrosekunden hat?

Ich portiere ein Spiel, das ursprünglich für die Win32-API geschrieben wurde, auf Linux (oder besser gesagt, ich portiere die OS X-Portierung der Win32-Portierung auf Linux).

Ich habe implementiert QueryPerformanceCounter durch Angabe der uSekunden seit dem Start des Prozesses:

BOOL QueryPerformanceCounter(LARGE_INTEGER* performanceCount)
{
    gettimeofday(&currentTimeVal, NULL);
    performanceCount->QuadPart = (currentTimeVal.tv_sec - startTimeVal.tv_sec);
    performanceCount->QuadPart *= (1000 * 1000);
    performanceCount->QuadPart += (currentTimeVal.tv_usec - startTimeVal.tv_usec);

    return true;
}

Dies, gepaart mit QueryPerformanceFrequency() mit einer konstanten Frequenz von 1000000, funktioniert gut auf meinem Rechner so dass ich eine 64-Bit-Variable erhalte, die Folgendes enthält uSeconds seit dem Start des Programms.

Also Ist das tragbar? Ich möchte nicht herausfinden, dass es anders funktioniert, wenn der Kernel auf eine bestimmte Weise kompiliert wurde oder so etwas. Ich habe jedoch kein Problem damit, dass es nicht auf andere Systeme als Linux portierbar ist.

9voto

Joe Shaw Punkte 21088

Es wird also ausdrücklich von Mikrosekunden gesprochen, aber die Auflösung der Systemuhr ist nicht spezifiziert. Ich nehme an, Auflösung in diesem Zusammenhang bedeutet, wie die kleinste Menge, die es jemals erhöht werden?

Die Datenstruktur ist so definiert, dass sie Mikrosekunden als Maßeinheit hat, aber das bedeutet nicht, dass die Uhr oder das Betriebssystem tatsächlich in der Lage ist, so fein zu messen.

Wie andere Leute vorgeschlagen haben, gettimeofday() ist ungünstig, weil das Einstellen der Uhrzeit zu Taktverzerrungen führen und die Berechnung verfälschen kann. clock_gettime(CLOCK_MONOTONIC) ist, was Sie wollen, und clock_getres() gibt Ihnen Auskunft über die Genauigkeit Ihrer Uhr.

0 Stimmen

Was passiert also in Ihrem Code, wenn gettimeofday() mit der Sommerzeit vorwärts oder rückwärts springt?

3 Stimmen

Clock_gettime ist nur auf dem neuesten Linux vorhanden. Andere Systeme haben nur gettimeofday()

6voto

bames53 Punkte 82553

Diese Antwort erwähnt Probleme mit der Einstellung der Uhr. Sowohl Ihre Probleme mit der Gewährleistung von Tick-Einheiten als auch die Probleme mit der Anpassung der Uhrzeit werden in C++11 mit dem <chrono> Bibliothek.

Die Uhr std::chrono::steady_clock wird garantiert nicht angepasst, und außerdem wird sie mit einer konstanten Rate relativ zur Echtzeit fortschreiten, so dass Technologien wie SpeedStep sie nicht beeinflussen dürfen.

Typsichere Einheiten erhalten Sie durch Konvertierung in eine der std::chrono::duration Spezialisierungen, wie zum Beispiel std::chrono::microseconds . Bei diesem Typ gibt es keine Unklarheiten über die Einheiten, die für den Tick-Wert verwendet werden. Beachten Sie jedoch, dass die Uhr nicht unbedingt diese Auflösung hat. Sie können eine Dauer in Attosekunden konvertieren, ohne eine so genaue Uhr zu haben.

4voto

Nach meiner Erfahrung und nach dem, was ich im Internet gelesen habe, lautet die Antwort "Nein", das ist nicht garantiert. Es hängt von der CPU-Geschwindigkeit, dem Betriebssystem, der Linux-Variante usw. ab.

3voto

Doug Punkte 1033

Das Auslesen der RDTSC ist in SMP-Systemen nicht zuverlässig, da jede CPU ihren eigenen Zähler unterhält und nicht gewährleistet ist, dass jeder Zähler in Bezug auf eine andere CPU synchronisiert ist.

Ich würde vorschlagen, Folgendes zu versuchen clock_gettime(CLOCK_REALTIME) . Das Posix-Handbuch gibt an, dass dies auf allen kompatiblen Systemen implementiert werden sollte. Es kann eine Nanosekunden-Zählung liefern, aber Sie werden wahrscheinlich überprüfen wollen clock_getres(CLOCK_REALTIME) auf Ihrem System, um zu sehen, wie hoch die Auflösung tatsächlich ist.

0 Stimmen

clock_getres(CLOCK_REALTIME) wird nicht die wirkliche Auflösung geben. Es wird immer "1 ns" (eine Nanosekunde) zurückgegeben, wenn hrtimers verfügbar sind, siehe include/linux/hrtimer.h Datei für define HIGH_RES_NSEC 1 (mehr unter stackoverflow.com/a/23044075/196561 )

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X