Schnellstes Timing-Resolution-System

8

Was ist das schnellste Timing-System, das ein C / C ++ - Programmierer verwenden kann?

Zum Beispiel:
time () gibt die Sekunden seit Jan 01 1970 00:00.
GetTickCount () unter Windows gibt die Zeit in Millisekunden seit der Startzeit des Systems an, ist aber auf 49,7 Tage begrenzt (danach wird es einfach auf Null zurückgestellt).

Ich möchte die aktuelle Zeit oder Ticks seit System / App Start-up-Zeit in Millisekunden abrufen.

Die größte Sorge ist der Overhead der Methode - ich brauche den leichtesten, weil ich es viele Male pro Sekunde nennen werde.

Mein Fall besteht darin, dass ich einen Arbeitsthread habe und zu diesem Arbeitsthread pendente Jobs posten. Jeder Job hat eine "Ausführungszeit". Also ist es mir egal, ob die Zeit die aktuelle "echte" Zeit oder die Zeit seit der Systembetriebszeit ist - sie muss einfach linear und leicht sein.

Bearbeiten:

%Vor%     
Poni 02.07.2010, 01:53
quelle

10 Antworten

15

Für das Timing empfiehlt die aktuelle Microsoft-Empfehlung , QueryPerformanceCounter & amp; QueryPerformanceFrequency .

Damit erhalten Sie ein besseres Timing als in Millisekunden. Wenn das System keinen Timer mit hoher Auflösung unterstützt, wird es standardmäßig auf Millisekunden eingestellt (das gleiche wie GetTickCount ).

Hier ist ein kurzer Microsoft-Artikel mit Beispielen, warum Sie es verwenden sollten :)

    
porges 02.07.2010, 01:59
quelle
5

Ich hatte diese Frage kürzlich und habe etwas recherchiert. Die gute Nachricht ist, dass alle drei Hauptbetriebssysteme eine Art hochauflösenden Timer zur Verfügung stellen. Die schlechte Nachricht ist, dass es auf jedem System einen anderen API-Aufruf gibt. Für POSIX-Betriebssysteme möchten Sie clock_gettime () verwenden. Wenn Sie unter Mac OS X arbeiten, wird dies jedoch nicht unterstützt. Sie müssen mach_get_time () verwenden. Verwenden Sie für Windows QueryPerformanceCounter. Bei Compilern, die OpenMP unterstützen, können Sie alternativ omp_get_wtime () verwenden, aber es bietet möglicherweise nicht die gewünschte Auflösung.

Ich fand auch, dass cycle.h von fftw.org (www.fftw.org/cycle.h) nützlich ist.

Hier ist ein Code, der auf jedem Betriebssystem einen Timer aufruft, mit einigen hässlichen #ifdef-Anweisungen. Die Verwendung ist sehr einfach: Timer t; t.tic (); SomeOperation (); t.toc ("Nachricht"); Und es wird die verstrichene Zeit in Sekunden ausdrucken.

%Vor%     
reso 02.07.2010 04:14
quelle
4

Wenn Sie nur besorgt sind, dass GetTickCount() überläuft, können Sie es einfach wie folgt umbrechen:

%Vor%

Wenn Sie dies aus mehreren Threads aufrufen möchten, müssen Sie den Zugriff auf die Variable last_tick sperren. Solange Sie GetLongTickCount() mindestens alle 49.7 Tage aufrufen, wird der Überlauf erkannt.

    
caf 02.07.2010 03:06
quelle
4

GetSystemTimeAsFileTime ist die schnellste Ressource . Seine Granularität kann erhalten werden durch einen Aufruf GetSystemTimeAdjustment , der lpTimeIncrement . Die Systemzeit als Dateizeit hat 100ns Einheiten und erhöht sich um TimeIncrement . TimeIncrement kann variieren und hängt von der Einstellung der Multimedia-Timer-Schnittstelle ab.

Ein Anruf bei timeGetDevCaps wird erfolgen offenbaren die Fähigkeiten der Zeitdienste. Es kehrt zurück ein Wert wPeriodMin für die minimale unterstützte Interrupt-Periode. Ein Aufruf an timeBeginPeriod mit wPeriodMin als Argument wird das System so einrichten, dass es mit der höchstmöglichen Interrupt-Frequenz arbeitet (normalerweise ~ 1 ms). Dies wird auch erzwingen, dass das Zeitinkrement der Systemdateizeit, die von GetSystemTimeAsFileTime zurückgegeben wird, kleiner ist. Seine Granularität liegt im Bereich von 1 ms (10000 100 ns Einheiten).

Für Ihren Zweck würde ich vorschlagen, für diesen Ansatz zu gehen.

Die QueryPerformanceCounter -Auswahl ist fraglich, da die Häufigkeit nicht hoch ist genau durch zwei Mittel: Erstens weicht es von dem Wert ab, der von QueryPerformanceFrequency durch einen hardwarespezifischen Offset. Dieser Offset kann leicht sein einige hundert ppm, was bedeutet, dass eine Umwandlung in die Zeit einen Fehler von mehreren hundert Mikrosekunden pro Sekunde enthält. Zweitens hat es thermische Drift. Die Drift solcher Vorrichtungen kann leicht mehrere ppm betragen. Auf diese Weise ein anderer - Hitze abhängiger - Fehler von mehrere us / s werden hinzugefügt.

Solange also eine Auflösung von ~ 1ms ausreicht und die Hauptfrage der Overhead ist, GetSystemTimeAsFileTime ist bei weitem die beste Lösung.

Wenn Mikrosekunden wichtig sind, müssen Sie einen längeren Weg gehen und mehr Details sehen. Sub-Millisekunden-Zeitdienste werden im Windows-Zeitstempelprojekt

beschrieben     
Arno 13.07.2012 16:23
quelle
1

Ich würde vorschlagen, dass Sie die GetSystemTimeAsFileTime API verwenden, wenn Sie zielen speziell auf Windows ab. Es ist in der Regel schneller als GetSystemTime und hat die gleiche Genauigkeit (das sind einige 10 -15 Millisekunden - nicht auf die Auflösung schauen); Als ich vor einigen Jahren unter Windows XP einen Benchmark gemacht habe, war es irgendwo im Bereich von 50-100 mal schneller.

Der einzige Nachteil besteht darin, dass Sie die zurückgegebenen FILETIME-Strukturen möglicherweise unter Verwendung von z. FileTimeToSystemTime , wenn Sie auf die zurückgegebenen Zeiten in einem benutzerfreundlicheren Modus zugreifen müssen Format. Solange Sie diese konvertierten Zeiten jedoch nicht in Echtzeit benötigen, können Sie dies immer offline oder "faul" machen (z. B. nur die Zeitstempel konvertieren, die Sie anzeigen / verarbeiten müssen, und nur wenn du sie wirklich brauchst).

QueryPerformanceCounter kann eine gute Wahl sein, wie andere bereits erwähnt haben Der Overhead kann abhängig von der zugrunde liegenden Hardware-Unterstützung ziemlich groß sein. In meinem Benchmark, den ich oben erwähnt habe, waren QueryPerformanceCounter-Aufrufe 25-200 Mal langsamer als Aufrufe von GetSystemTimeAsFileTime. Außerdem gibt es einige Zuverlässigkeitsprobleme, wie z.B. berichtet hier .

Also, zusammenfassend: Wenn Sie eine Genauigkeit von 10-15 Millisekunden bewältigen können, würde ich Ihnen empfehlen, GetSystemTimeAsFileTime zu verwenden. Wenn Sie etwas besseres als das brauchen, würde ich für QueryPerformanceCounter gehen.

Kleiner Haftungsausschluss: Ich habe kein Benchmarking unter späteren Windows-Versionen als XP SP3 durchgeführt. Ich würde dir empfehlen, ein Benchmarking auf eigene Faust durchzuführen.

    
rjnilsson 02.07.2010 05:34
quelle
0

Unter Linux erhalten Sie Mikrosekunden:

%Vor%

Unter Windows sind nur Millisekunden verfügbar:

%Vor%

Dies kam von R datetime.c (und wurde aus Platzgründen kurz geschnitten).

Dann gibt es natürlich Boost's Date_Time mit einer Auflösung von Nanosekunden einige Systeme (Details hier und hier ).

    
Dirk Eddelbuettel 02.07.2010 02:03
quelle
0

Wenn Sie eine späte Version des Betriebssystems verwenden, können Sie % verwenden. co_de% , das einen viel höheren Umbruchpunkt als GetTickCount64() . Sie könnten auch einfach eine Version von GetTickCount() über GetTickCount64() erstellen.

    
Len Holgate 15.07.2010 10:16
quelle
0

Haben Sie den Code in diesem MSDN-Artikel überprüft?

Ссылка

Ich habe diesen Code kompiliert auf einem Windows 7 64-Bit-Computer mit VC2005 und C ++ Builder XE, aber bei der Ausführung stört es meine Maschine; habe nicht weit genug debugged, um herauszufinden, warum noch nicht. Es scheint übermäßig kompliziert. Vorlagen von Vorlagen von Vorlagen von UG ...

    
Eric 24.01.2011 20:26
quelle
0

Unter Mac OS X können Sie UInt32 TickCount (void) einfach verwenden, um die Ticks zu erhalten.

    
Robby Shaw 05.03.2013 06:03
quelle
0

POSIX unterstützt clock_gettime () , das ein struct timespec mit einer Auflösung von Nanosekunden. Ob Ihr System wirklich diese fein abgestufte Auflösung unterstützt, ist umstrittener, aber ich glaube, das ist der Standardanruf mit der höchsten Auflösung. Nicht alle Systeme unterstützen es, und es ist manchmal gut versteckt (Bibliothek ' -lposix4 ' auf Solaris, IIRC).

Update (2016-09-20):

  • Obwohl Mac OS X 10.6.4 clock_gettime() nicht unterstützt hat und auch keine andere Version von Mac OS X bis einschließlich Mac OS X 10.11.6 El Capitan), hat macOS Sierra 10.12 die Funktion clock_gettime() und manuelle Seiten dafür endlich. Die tatsächliche Auflösung (in CLOCK_MONOTONIC ) ist immer noch Mikrosekunden; die kleineren Einheiten sind alle Nullen. Dies wird durch clock_getres() bestätigt, das berichtet, dass die Auflösung 1000 Nanosekunden beträgt, auch bekannt als 1 μs.

Die Handbuchseite für clock_gettime() auf macOS Sierra erwähnt mach_absolute_time() als eine Möglichkeit, ein hochauflösendes Timing zu erhalten. Weitere Informationen finden Sie unter Technische Fragen und Antworten zu A QA1398: Mach Absolute Time Units und (auf SO) Was ist mach_absolute_time() basierend auf on iPhone?

    
Jonathan Leffler 02.07.2010 03:20
quelle

Tags und Links