Wie erstelle ich einen hochauflösenden Timer in Linux, um die Programmleistung zu messen?
Lesezeit: 9 Minuten
sj755
Ich versuche, die GPU- mit der CPU-Leistung zu vergleichen. Für die NVIDIA-GPU habe ich die verwendet cudaEvent_t Typen, um ein sehr genaues Timing zu erhalten.
Für die CPU habe ich folgenden Code verwendet:
// Timers
clock_t start, stop;
float elapsedTime = 0;
// Capture the start time
start = clock();
// Do something here
.......
// Capture the stop time
stop = clock();
// Retrieve time elapsed in milliseconds
elapsedTime = (float)(stop - start) / (float)CLOCKS_PER_SEC * 1000.0f;
Anscheinend ist dieser Code nur dann gut, wenn Sie in Sekunden zählen. Außerdem kommen die Ergebnisse manchmal ziemlich seltsam heraus.
Kennt jemand eine Möglichkeit, einen hochauflösenden Timer unter Linux zu erstellen?
Siehe diese Frage: stackoverflow.com/questions/700392/…
– Steve-o
19. Juli 2011 um 15:26 Uhr
NPE
Kasse clock_gettimedas eine POSIX-Schnittstelle zu hochauflösenden Timern ist.
Wenn Sie sich nach dem Lesen der Manpage über den Unterschied zwischen wundern CLOCK_REALTIME und CLOCK_MONOTONICsiehe Unterschied zwischen CLOCK_REALTIME und CLOCK_MONOTONIC?
Nur damit ich klar bin, was ich gelesen habe, können Sie mir ein Beispiel geben, wie Sie clock_gettime verwenden würden, um die verstrichene Zeit in Nanosekunden zu finden?
– sj755
19. Juli 2011 um 16:05 Uhr
@seljuq70: Ich habe einen Link zu einem vollständigen Beispiel hinzugefügt.
– NPE
19. Juli 2011 um 17:01 Uhr
OP wurde C geschrieben, aber Ihre Antwort ist C++. Immer noch nützlich, aber nicht auf meinem ZedBoard, das keine C++-Bibliotheken hat 😀 Um das zu beheben, stellen Sie der Zeitangabe struct voran und entfernen Sie die Couts.
– Eule
6. August 2018 um 10:32 Uhr
Die Antwort spricht also ausdrücklich von CLOCK_REALTIME und CLOCK_MONOTONIC aber wir enden mit CLOCK_PROCESS_CPUTIME_ID im Codebeispiel? Kann das jemand klären? Was soll gehen?
– itMaxence
30. August 2018 um 10:05 Uhr
@itMaxence Schauen Sie sich das an: stackoverflow.com/a/3527632/9732482
– jplozier
10. Juni 2021 um 13:48 Uhr
Alex
Um die bisher vorgestellten Informationen zusammenzufassen, sind dies die beiden Funktionen, die für typische Anwendungen erforderlich sind.
#include <time.h>
// call this function to start a nanosecond-resolution timer
struct timespec timer_start(){
struct timespec start_time;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time);
return start_time;
}
// call this function to end a timer, returning nanoseconds elapsed as a long
long timer_end(struct timespec start_time){
struct timespec end_time;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_time);
long diffInNanos = (end_time.tv_sec - start_time.tv_sec) * (long)1e9 + (end_time.tv_nsec - start_time.tv_nsec);
return diffInNanos;
}
Hier ist ein Beispiel dafür, wie man sie beim Timing verwendet, wie lange es dauert, die Varianz einer Eingabeliste zu berechnen.
struct timespec vartime = timer_start(); // begin a timer called 'vartime'
double variance = var(input, MAXLEN); // perform the task we want to time
long time_elapsed_nanos = timer_end(vartime);
printf("Variance = %f, Time taken (nanoseconds): %ld\n", variance, time_elapsed_nanos);
Ignorierst du nicht die tv_sec des timespec? Auch warum CLOCK_PROCESS_CPUTIME_ID statt CLOCK_MONOTONIC?
– Amaurea
28. Februar 2014 um 17:37 Uhr
Das Poster vergleicht die CPU- mit der GPU-Leistung. Sie geben ehrlich Code, der die CPU-Zeit erhält. CLOCK_PROCESS_CPUTIME_ID. Dies bedeutet, dass er um viele Größenordnungen beschleunigt wird. Verwenden Sie für die CPU / GPU-Leistung (diese Frage) immer die Wandzeit. Entfernen Sie diese Antwort.
– Tim Zaman
22. Juni 2016 um 12:15 Uhr
@TimZaman Ja, Echtzeit könnte im Anwendungsfall des Posters besser sein. Ich werde jedoch keine Antwort notieren, offensichtlich fanden die Leute es nützlich. Prost.
– Alex
23. Juni 2016 um 8:29 Uhr
Bevor Sie CLOCK_PROGRESS_CPUTIME_ID verwenden, sollten Sie ausführen grep constant_tsc /proc/cpuinfo um zu verstehen, wie diese Uhr funktioniert. Wenn Sie CPU nicht unterstützt konstant_tsc, spiegelt die Zeit die tatsächlichen CPU-Taktzyklen wider. Wenn das Flag gesetzt ist, wird die Uhr angepasst, um die aktuelle CPU-Frequenz zu berücksichtigen. Ich gebe diesem eine -1, weil time_elapsed_nanos wird falsch berechnet. Dies vielleicht ein besserer Ansatz.
es gibt auch CLOCK_REALTIME_HR, aber ich bin mir nicht sicher, ob es einen Unterschied macht.
Und ich bin mir nicht sicher, ob CLOCK_REALTIME_HR wird unterstützt. Frage.
– Gsamaras
7. September 2017 um 11:13 Uhr
Interessieren Sie sich für Wall Time (wie viel Zeit vergeht tatsächlich) oder Cycle Count (wie viele Zyklen)? Im ersten Fall sollten Sie etwas wie verwenden gettimeofday.
Der Timer mit der höchsten Auflösung verwendet die RDTSC x86 Montageanleitung. Dies misst jedoch die Taktzeiten, daher sollten Sie sicher sein, dass der Energiesparmodus deaktiviert ist.
Nachdem ich diesen Thread gelesen hatte, begann ich, den Code für clock_gettime gegen den Chrono von c++ 11 zu testen, und sie scheinen nicht übereinzustimmen.
Dazwischen klafft eine riesige Lücke!
Das std::chrono::Sekunden(1) scheint gleichwertig zu sein ~70.000 des clock_gettime
Hello waiter
0 Waited (0 s 000843254 ns)
1 Waited (0 s 000681141 ns)
2 Waited (0 s 000685119 ns)
3 Waited (0 s 000674252 ns)
4 Waited (0 s 000714877 ns)
5 Waited (0 s 000624202 ns)
6 Waited (0 s 000746091 ns)
7 Waited (0 s 000575267 ns)
8 Waited (0 s 000860157 ns)
9 Waited (0 s 000827479 ns)
10 Waited (0 s 000612959 ns)
11 Waited (0 s 000534818 ns)
12 Waited (0 s 000553728 ns)
13 Waited (0 s 000586501 ns)
14 Waited (0 s 000627116 ns)
15 Waited (0 s 000616725 ns)
16 Waited (0 s 000616507 ns)
17 Waited (0 s 000641251 ns)
18 Waited (0 s 000683380 ns)
19 Waited (0 s 000850205 ns)
Ich denke ++temp.tv_sec; ist ein Typ und Sie meinten –temp.tv_sec; in der diff-Funktion.
– Simone-Cu
21. März um 17:27 Uhr
Es ist kein Typ, wenn ich die 2 Strukturen subtrahiere, berücksichtige ich, dass es einen geben könnte Übertrag
– radato
22. März um 8:53 Uhr
Ja, das verstanden. Aber wenn Sie den Übertrag von s auf ns durchführen, sollten Sie 1 vom Sekundenfeld subtrahieren und 1000000000 (1s) zum ns-Feld addieren. Sagen wir (10s and 900ns) - (5s and 1000ns) –> 5s and -100ns –> 4s and (-100+10^9)ns. Der letzte Schritt verringert die Sekunde und führt so den Übertrag aus.
– Simone-Cu
23. März um 15:42 Uhr
Ja richtig, ich habe die Antwort entsprechend korrigiert
Ich denke ++temp.tv_sec; ist ein Typ und Sie meinten –temp.tv_sec; in der diff-Funktion.
– Simone-Cu
21. März um 17:27 Uhr
Es ist kein Typ, wenn ich die 2 Strukturen subtrahiere, berücksichtige ich, dass es einen geben könnte Übertrag
– radato
22. März um 8:53 Uhr
Ja, das verstanden. Aber wenn Sie den Übertrag von s auf ns durchführen, sollten Sie 1 vom Sekundenfeld subtrahieren und 1000000000 (1s) zum ns-Feld addieren. Sagen wir (10s and 900ns) - (5s and 1000ns) –> 5s and -100ns –> 4s and (-100+10^9)ns. Der letzte Schritt verringert die Sekunde und führt so den Übertrag aus.
– Simone-Cu
23. März um 15:42 Uhr
Ja richtig, ich habe die Antwort entsprechend korrigiert
Siehe diese Frage: stackoverflow.com/questions/700392/…
– Steve-o
19. Juli 2011 um 15:26 Uhr