2013-06-01 17 views
18

Ich habe festgestellt, dass das erste Mal, wenn ich ein Skript ausführe, wesentlich mehr Zeit benötigt als das zweite und dritte Mal. Das "Aufwärmen" wird in this question ohne Erklärung erwähnt. Ich frage mich, warum läuft der Code schneller, nachdem er "aufgewärmt" ist? Ich nicht clear all zwischen den Anrufen, aber die Eingabeparameter ändern sich für jeden Funktionsaufruf. Weiß jemand, warum das so ist?Warum läuft Matlab schneller, nachdem ein Skript "aufgewärmt" wurde?

+0

Eine wichtige Frage ist: Möchten Sie mehrere Matlab-Prozesse vergleichen * oder * wollen Sie Matlab-Implementierungen mit anderen vergleichen (Fortran, C, Octave, ...)? Im zweiten Fall ist ein fairer Vergleich sehr schwer zu erreichen. –

+0

@MarcClaesen: Ich vergleiche nur Matlab processes =) –

+0

Vielleicht benutzen Sie auch Online-Lizenzserver wie hier. In diesem Fall dauert das Auschecken der Lizenzen ziemlich lange. Übrigens. Was passiert mit der Zeit, wenn Sie zwischen den Läufen alles löschen? – Trilarion

Antwort

8

Ein Grund, warum es nach dem ersten Mal schneller laufen würde, ist, dass viele Dinge einmal initialisiert werden und ihre Ergebnisse zwischengespeichert und beim nächsten Mal wiederverwendet werden. Zum Beispiel können in der M-Seite Variablen definiert werden als persistent in Funktionen, die locked sein können. Dies kann auch auf die MEX - side der Dinge auftreten.

Zusätzlich werden viele Abhängigkeiten nach dem ersten Mal geladen und bleiben so im Speicher, um wiederverwendet zu werden. Dazu gehören M-Funktionen, OOP-Klassen, Java-Klassen, MEX-Funktionen und so weiter. Dies gilt sowohl für integrierte als auch für benutzerdefinierte.

Zum Beispiel geben Sie die folgenden command vor und nach dem Drehbuch für den ersten Durchlauf läuft, dann vergleichen:

[M,X,C] = inmem('-completenames') 

Beachten Sie, dass clear all nicht unbedingt clear alle der oben genannten, nicht gesperrte Funktionen zu erwähnen .. .

Schließlich vergessen wir nicht die Rolle des Beschleunigers. Anstatt den M-Code jedes Mal zu interpretieren, wenn eine Funktion aufgerufen wird, wird er zur Laufzeit in Maschinencodeanweisungen kompiliert. Die JIT-Kompilierung findet nur für den ersten Aufruf statt. Idealerweise wird die Effizienz der Ausführung des Objektcodes die folgenden Male den Overhead des erneuten Interpretierens des Programms bei jeder Ausführung überwinden.

+0

Danke Amro! Weißt du, ob das Skript schneller läuft, wenn nur die notwendigen Programme im P-Code-Puffer sind, und nicht alle Dinge, die in anderen Funktionsaufrufen verwendet werden, an denen ich nicht interessiert bin? I.e. sollte ich "alles löschen", bevor ich ein bestimmtes Skript benchmarkiere? Ich habe keinen signifikanten Unterschied bemerkt, aber ich habe den Puffer auch nicht "aufgefüllt" ... –

+1

Amro, Es sei denn, dein Code ist ziemlich klein, JIT Compilation ist der primäre Effekt bei der Beschleunigung von Code in Läufen nach dem ersten - Ladefunktionen sind nicht so wichtig. Darüber hinaus tritt die JIT-Kompilierung nicht nur beim ersten Aufruf auf - MATLAB übersetzt manchmal nur JIT-Teile Ihres Codes beim ersten Durchlauf und andere Teile später. @RobertP., Wenn Sie Code benchmarken müssen, ist die 'timeit'-Funktion, auf die in der von Ihnen referenzierten Frage verwiesen wird, der beste Weg, dies zu tun. Unter anderem behandelt es alle Aufwärmprobleme, die Sie für Sie beschreiben. –

+0

@SamRoberts: Ich stimme zu, das ist sicherlich das Versprechen der JIT Compilation. Wenn ein Codeabschnitt wiederholt aufgerufen wird, erwarten wir, dass der JIT-Compiler diesen "Hot-Spot" zur Laufzeit erkennt und in direkten Maschinencode optimiert. Hoffentlich auch wenn nicht alle im selben Lauf. Was das Laden von Funktionen angeht, denke ich, dass es eher ein Problem für MEX-Funktionen ist, wo der Aufwand für das Laden externer Abhängigkeiten höher ist. – Amro

2

wird interpretiert. Wenn Sie den Code nicht aufwärmen, verlieren Sie viel Zeit aufgrund der Interpretation anstelle des eigentlichen Algorithmus. Dies kann die Ergebnisse von Zeitsteuerungen signifikant verzerren.

Wenn Sie den Code ein paar Mal ausführen, wird aktiviert, um entsprechende Codesegmente zu kompilieren.

0

Ein anderes Problem, das nicht von Amro und Marc mensioned ist, ist die Speicherzuweisung (vor).
Wenn Ihr Skript seinen Arbeitsspeicher nicht vorbelegt, ist der erste Durchlauf aufgrund der Speicherzuweisung sehr langsam. Sobald die erste Iteration abgeschlossen ist, wird der gesamte Speicher zugewiesen, so dass aufeinanderfolgende Aufrufe des Skripts effizienter wären.

Ein anschauliches Beispiel

for ii = 1:1000 
    vec(ii) = ii; %// vec grows inside loop the first time this code is executed only 
end 
+3

@Shai hat Recht bezüglich Vorbelegung, aber ich möchte über die Konsequenzen nicht übereinstimmen. Code, der so etwas macht, ist * schlecht geschrieben *. Das Aufwärmen dieser Art von Code wird es beim nächsten Mal schneller machen, aber in diesem Fall * ist der Algorithmus schlecht *. Das ist der Grund, warum ich denke, dass in diesem Fall das Aufwärmen die Timings im Vorteil des schlechten Codes verzerrt und schlechte Implementierungen maskiert! –

+0

@Shai Preallocation ist eine gute Sache, aber es hat die gleichen Auswirkungen auf die ersten und nachfolgenden Aufrufe. In Ihrem Beispiel wächst 'vec' nicht nur beim ersten Ausführen des Codes, sondern bei jeder Ausführung des Codes. –

+0

@Shai, tut mir leid, das ist nicht ganz richtig, da dies innerhalb eines Skripts ist, also wäre 'vec' bereits vorhanden, wenn Sie das Skript erneut ausführen würden. Wenn es in einer Funktion war, wuchs es jedes Mal, wenn der Code ausgeführt wurde, nicht nur der erste. –

1

Neben Matlab spezifischen Gründen wie JIT-Kompilierung, haben moderne CPUs großen Caches, Verzweigungsvorhersager, und so weiter. Das Aufheizen ist ein Problem für das Benchmarking selbst in der Assemblersprache.

Noch wichtiger ist, dass moderne CPUs in der Regel bei niedriger Taktfrequenz im Leerlauf sind und erst nach mehreren Millisekunden Dauerlast auf die volle Drehzahl springen.

Intels Turbo Feature wird noch flippiger: Wenn es die Leistungs- und Temperaturgrenzen zulassen, kann die CPU schneller als ihre nachhaltige maximale Frequenz laufen. Die ersten ~ 20 Sekunden bis 1 Minute Ihres Benchmarks laufen möglicherweise schneller als der Rest, wenn Sie diese Faktoren nicht kontrollieren.

Verwandte Themen