2016-06-19 8 views
2

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.

+3

Verwenden Sie ein anständiges Profiling-Tool wie "perf", sonst erhalten Sie nicht die ganze Geschichte. –

+1

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

+2

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

Antwort

1

Moderne CPUs haben dynamisch wechselnde Frequenz, man sollte nicht nur Wandzeit (astronomische Zeit) messen, sondern auch die Anzahl der CPU-Zyklen. perf stat (eigentlich, perf stat -e task-clock,cycles,instructions ist genug) zeigt Ihnen mittlere CPU-Kern-Frequenz, während das Programm in Zeile cycles lief, wenn es CPU-Clock/Task-Clock-Ereignis zu Wandzeit messen (Zyklen geteilt Zeit um GHz zu erhalten):

#### cycles     # 1,653 GHz  

#### cycles     # 2,579 GHz 

Dies ist Intel Turbo-Boost (2), https://en.wikipedia.org/wiki/Intel_Turbo_Boost (AMD hat https://en.wikipedia.org/wiki/AMD_Turbo_Core). Beide sind sehr schnell, wenn also cpupower -c all frequency-info läuft, ist die tatsächliche Frequenz niedrig (1,3); aber wenn es eine hohe Last von Ihrem Programm gibt, skaliert die CPU ihre Frequenz auf einige Mikrosekunden.

Manchmal ist es möglich, es im BIOS zu deaktivieren einheitlichere Messungen zu erhalten: http://www.intel.com/content/www/us/en/support/processors/000005641.html

Wie wird die Intel® Turbo-Boost-Technologie aktiviert oder deaktiviert? - Die Intel® Turbo Boost-Technologie ist standardmäßig standardmäßig aktiviert. Sie können die Technologie nur über einen Schalter im BIOS deaktivieren und aktivieren. Es gibt keine anderen benutzersteuerbaren Einstellungen.

Oder Sie können etwas Magie MSR Schreiben versuchen (nicht schreiben zufällige Werte in zufälliger msr regs, kann es etwas brechen, oder hängen PC): https://askubuntu.com/questions/619875/disabling-intel-turbo-boost-in-ubuntu Antwort von Maythux: „wrmsr -pC 0x1a0 0x4000850089

Andere Linien von perf stat: 7361-7360 mln Anweisungen, 1228-1227 mln Verzweigungen 64 Millionen Verzweigungsfehlvorgaben zeigen an, dass das Programm das gleiche war und es wurde der gleiche Code ausgeführt (keine externe Zufallsauswahl).Sie können auch versuchen perf stat -d (besser ist, einige funktionierende Hardware-Ereignisse aus stat -d auszuwählen und sie manuell in perf stat -e cpu-clock,.... auflisten), um Cache-Ereignisunterschied zwischen Läufen zu überprüfen.

+0

Wenn Turbo im BIOS aktiviert ist, können Sie es von Linux mit einigen MSR-Schreiben Magie deaktivieren - http://askubuntu.com/questions/619875/disabling-intel-turbo-boost-in-ubuntu – osgx

+1

Dies ist wahrscheinlich die Antwort, die ich wurde gesucht! Deaktivierung von beiden, Turbo Boost (mit 'wrmsr') und Frequenzskalierung (mit 'cpupower'), jetzt bekomme ich viel mehr vertrauenswürdige Ergebnisse. Der beste Lauf des Testprogramms unter vielen war 9,81s , während der schlechteste ist 10,74s. In beiden Fällen habe ich Zyklen = 1.293 GHz. Für den schnellsten Lauf habe ich Zweige = 124.906 M/sec und L1-dcache-Lasten = 214.174 M/sec während für den langsamsten Lauf habe ich Zweige = 114.328 M/sec und L1-dcache-Lasten = 194.013 M/sec . Ich weise diese Unterschiede dem Programm selbst zu (z. B. Hash-Tabellen) und nicht dem System. – meolic

+0

Ich habe auch versucht, Turbo Boost mit dem Befehl 'Echo "0">/sys/devices/system/cpu/cpufreq/boost' zu deaktivieren, weil der Frequenzskalierung Treiber auf meinem System acpi-cpufreq ist. Erfolglos. – meolic

0

Ein Betriebssystem führt mehrere Tasks gleichzeitig aus und um es zu verwalten, wechselt es von einer Task zur anderen. Daher ist es nicht die Zeit Ihres Codes, die sich jedes Mal ändert, sondern die anderen Programme, die vom Betriebssystem zwischen der Ausführung Ihres Programms aufgerufen werden.

+1

Ich brauche einen Beweis für eine solche Behauptung. Und ich denke, dass Ergebnisse, die von perf erhalten werden, dies nicht unterstützen. Liege ich falsch? – meolic