Nun, das wird eine Frage ohne Details sein, weil ich nicht weiß, wie man besser erklärt. Es tut uns leid. Ich habe ein speicherintensives C-Programm (viele Zeiger). Ich habe eine Quelle, sie wird von mir mit gcc -O2 kompiliert. Ich bin auf Ubuntu Linux. Am Anfang und Ende des Programms gibt es einen Aufruf von clock(), um die verstrichene Zeit zu messen. Außerdem verwende ich den Zeitbefehl, um die Zeit zu überprüfen. Das Problem ist, dass das gleiche Programm manchmal mehr als 20% schneller (oder langsamer) ist, ohne etwas zu ändern.Warum ist das gleiche C-Programm manchmal viel schneller
$ date; time ./cudd-example-8queens
pon jun 20 00:49:05 CEST 2016
CPU TIME = 6.46
real 0m6.475s
user 0m6.405s
sys 0m0.067s
$ date; time ./cudd-example-8queens
pon jun 20 00:49:16 CEST 2016
CPU TIME = 8.03
real 0m8.051s
user 0m7.995s
sys 0m0.048s
$ date; time ./cudd-example-8queens
pon jun 20 00:49:33 CEST 2016
CPU TIME = 6.48
real 0m6.490s
user 0m6.445s
sys 0m0.040s
$ date; time ./cudd-example-8queens
pon jun 20 00:49:42 CEST 2016
CPU TIME = 6.45
real 0m6.469s
user 0m6.424s
sys 0m0.040s
$ date; time ./cudd-example-8queens
pon jun 20 00:49:56 CEST 2016
CPU TIME = 8.04
real 0m8.058s
user 0m7.982s
sys 0m0.068s
Meine Frage ist: wie diese Unterschiede zu erklären, das heißt wo diese zusätzliche 1.5s (manchmal sogar noch schlimmer) ausgegeben? Es muss etwas mit Speicherzugriff sein, aber wie überprüft man das?
EDIT: Ich habe Perf installiert und hier sind zwei Ergebnisse (Ich habe sie aktualisiert, um auch Informationen von cpupower erhalten anzuzeigen). Hinsichtlich der Ziele vergleiche ich wissenschaftliche Algorithmen und es ist wichtig für mich, wenn z.B. Eins ist 10% schneller als andere.
$ date; cpupower -c all frequency-info -f; perf stat -B ./cudd-example-8queens
pon jun 20 12:39:21 CEST 2016
analyzing CPU 0:
1300000
analyzing CPU 1:
1300000
analyzing CPU 2:
1300000
analyzing CPU 3:
1300000
clock() TIME = 6.70
clock_gettime() TIME = 6.70
Performance counter stats for './cudd-example-8queens':
6705,796274 task-clock (msec) # 0,999 CPUs utilized
104 context-switches # 0,016 K/sec
3 cpu-migrations # 0,000 K/sec
30861 page-faults # 0,005 M/sec
17295862806 cycles # 2,579 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
7361712951 instructions # 0,43 insns per cycle
1228059232 branches # 183,134 M/sec
64491733 branch-misses # 5,25% of all branches
6,709414218 seconds time elapsed
$ date; cpupower -c all frequency-info -f; perf stat -B ./cudd-example-8queens
pon jun 20 12:39:30 CEST 2016
analyzing CPU 0:
1300000
analyzing CPU 1:
1300000
analyzing CPU 2:
1300000
analyzing CPU 3:
1300000
clock() TIME = 8.43
clock_gettime() TIME = 8.43
Performance counter stats for './cudd-example-8queens':
8441,824238 task-clock (msec) # 0,999 CPUs utilized
145 context-switches # 0,017 K/sec
3 cpu-migrations # 0,000 K/sec
30863 page-faults # 0,004 M/sec
13958245339 cycles # 1,653 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
7360082448 instructions # 0,53 insns per cycle
1227803521 branches # 145,443 M/sec
64517871 branch-misses # 5,25% of all branches
8,446645648 seconds time elapsed
EDIT2: Mein Intel NUC hat Intel Core i5-4250U CPU. Daher war der Ratschlag, "cpupower frequency-set" zu verwenden, vielversprechend, aber leider hilft es nichts. Außerdem bekomme ich mit "clock()" und "clock_gettime (CLOCK_PROCESS_CPUTIME_ID) genau die gleichen Ergebnisse und diese Ergebnisse werden auch von" task-clock (msec) "von perf bestätigt.
Verwenden Sie ein anständiges Profiling-Tool wie "perf", sonst erhalten Sie nicht die ganze Geschichte. –
Was ich gesagt habe ... und du bist in einer Multi-User-Multitasking-Umgebung. Timing einer einzelnen Aufgabe kann neben sinnlos sein. .. und dann gibt es z.B. Der Zustand der Sache/dev/urandom Wenn Sie das verwenden ... – tink
Wenn Sie die Geschwindigkeit eines Programms messen, ist die "verstrichene Zeit" fast nutzlos, da sie die Zeit einschließt, wenn andere Prozesse laufen. Eine bessere Methode würde lauten: clock_gettime() mit dem Parameter: CLOCK_PROCESS_CPUTIME_ID, wodurch die Prozesszeit für den aktuellen Prozess berechnet wird. Hinweis: Achten Sie immer auf einen zurückgegebenen Wert von "-1", da dies ein Anzeichen dafür ist, dass der Anruf fehlgeschlagen ist. Hinweis: Die erste Zeile in Ihrem Programm sollte sein: '#define _POSIX_C_SOURCE (199309L)' – user3629249