2013-07-23 7 views
10

In dem Versuch zu wählen, welche Indexierungsmethode zu empfehlen, habe ich versucht, die Leistung zu measeure. Die Messungen haben mich jedoch sehr verwirrt. Ich habe das mehrfach in verschiedenen Reihenfolgen ausgeführt, aber die Messungen bleiben konsistent. Hier ist, wie ich die Leistung gemessen:Leistung der Indexerstellung

for N = [10000 15000 100000 150000] 
    x = round(rand(N,1)*5)-2; 
    idx1 = x~=0; 
    idx2 = abs(x)>0; 

    tic 
    for t = 1:5000 
     idx1 = x~=0; 
    end 
    toc 

    tic 
    for t = 1:5000 
     idx2 = abs(x)>0; 
    end 
    toc 
end 

Und das ist das Ergebnis:

Elapsed time is 0.203504 seconds. 
Elapsed time is 0.230439 seconds. 

Elapsed time is 0.319840 seconds. 
Elapsed time is 0.352562 seconds. 

Elapsed time is 2.118108 seconds. % This is the strange part 
Elapsed time is 0.434818 seconds. 

Elapsed time is 0.508882 seconds. 
Elapsed time is 0.550144 seconds. 

I geprüft und für Werte um 100000 dies geschieht auch, selbst bei 50000 die seltsamen Messungen auftreten.

Also meine Frage ist: Hat jemand anderes dies für einen bestimmten Bereich erfahren, und was verursacht das? (Ist es ein Fehler?)

+0

Nun, ich würde auf jeden Fall davon ausgehen, 'abs (x)> 0 'würde langsamer sein, weil es wirklich zwei Operationen tut, aber die N-Studie von 100000, bedeutet dies nicht folgen. Seltsam. Ich würde jedoch fast immer 'x ~ = 0' verwenden, weil es nur eine Operation ausführt. Beachten Sie auch, der Unterschied zwischen den beiden war nicht so hoch für mich wie für Sie. Der dritte Versuch wurde nur um 0,4 Sekunden getrennt, nicht 1.5 – MZimmerman6

+0

mein einziger Gedanke wäre, es wäre eine seltsame Speicherzuweisung im Hintergrund, die der 100k Versuch wirft – MZimmerman6

+0

Ich sehe die gleiche Sache, aber nicht so drastisch (R2012b, OS X 10.8.4). Ich würde nicht annehmen, dass "abs (x)> 0" zwei Operationen ausführt. Sobald JIT kompiliert wurde, kann das Vorzeichenbit in dem Vergleich ignoriert werden. Es ist eigentlich der 'x ~ = 0'-Fall, der komplizierter ist (äquivalent zu 'x> 0 | x <0'). Ein möglicher Grund für den Unterschied zwischen den Größen könnte [Cache fehlt] sein (https://en.wikipedia.org/wiki/CPU_cache#Cache_miss), das im Detail [hier] (http://stackoverflow.com/questions) diskutiert wird/8547778/warum-ist-eine-Schleife-so-viel-langsamer-als-zwei-Schleifen). – horchler

Antwort

6

mit diesem zu einem gewissen automatischen Optimierung Matlab zurückzuführen kann verwendet für seine Basic Linear Algebra Unterprogramm.

Genau wie Sie, dauert meine Konfiguration (OSX 10.8.4, R2012a mit Standardeinstellungen) länger, um idx1 = x~=0 für x (10e5 Elemente) als x (11e5 Elemente) zu berechnen. Siehe das linke Feld der Figur, wo die Verarbeitungszeit (y-Achse) für verschiedene Vektorgrößen (x-Achse) gemessen wird. Sie sehen eine kürzere Verarbeitungszeit für N> 103000. In diesem Fenster habe ich auch die Anzahl der Kerne angezeigt, die während der Berechnung aktiv waren. Sie werden sehen, dass für die Ein-Kern-Konfiguration kein Abfall vorliegt. Dies bedeutet, dass Matlab die Ausführung von ~= nicht optimiert, wenn 1 Kern aktiv ist (keine Parallelisierung möglich). Matlab ermöglicht einige Optimierungsroutinen, wenn zwei Bedingungen erfüllt sind: mehrere Kerne und ein Vektor ausreichender Größe.

Im rechten Bereich werden die Ergebnisse angezeigt, wenn feature('accel','on'/off') auf Aus gestellt ist (doc). Hier ist nur ein Kern aktiv (1-Kern und 4-Kern sind identisch) und daher ist keine Optimierung möglich.

Die Funktion zum Aktivieren/Deaktivieren der Kerne ist schließlich maxNumCompThreads. Gemäß Loren Shure steuert maxNumCompThreads sowohl das JIT als auch BLAS. Da bei der Performance keine Rolle spielte, ist BLAS die letzte verbleibende Option.

Ich überlasse den letzten Satz an Loren: "Die wichtigste Nachricht hier ist, dass Sie diese Funktion [maxNumCompThreads] überhaupt nicht verwenden sollten! Warum? Weil wir möchten, dass MATLAB den besten Job macht möglich für dich. "enter image description here

accel = {'on';'off'}; 
figure('Color','w'); 
N = 100000:1000:105000; 

for ind_accel = 2:-1:1 
    eval(['feature(''accel'',''' accel{ind_accel} ''')']); 
    tElapsed = zeros(4,length(N)); 
    for ind_core = 1:4 
     maxNumCompThreads(ind_core); 
     n_core = maxNumCompThreads; 
     for ii = 1:length(N) 
      fprintf('core asked: %d(true:%d) - N:%d\n',ind_core,n_core, ii); 
      x = round(rand(N(ii),1)*5)-2; 
      idx1 = x~=0; 
      tStart = tic; 
      for t = 1:5000 
       idx1 = x~=0; 
      end 
      tElapsed(ind_core,ii) = toc(tStart); 
     end 
    end 
    h2 = subplot(1,2,ind_accel); 
    plot(N, tElapsed,'-o','MarkerSize',10); 
    legend({('1':'4')'}); 
    xlabel('Vector size','FontSize',14); 
    ylabel('Processing time','FontSize',14); 
    set(gca,'FontSize',14,'YLim',[0.2 0.7]); 
    title(['accel ' accel{ind_accel}]); 
end 
+0

Ich schätze, dass idealerweise Optimierungen einsetzen würden, sobald sie zu einem besseren Ergebnis führen. Also, wenn ich richtig verstehe: Für diese Operation (auf unseren Computern) kommt die Optimierung einfach zu spät? –

+0

yep - Sie haben einen der "besten Job für Sie" Einstellungen/Limit gefunden. Aber Matlabs Entwickler sind sich dessen bewusst und haben das absichtlich getan. – marsei

7

Ich denke, das ist etwas mit JIT zu tun (Ergebnisse unten sind 2011b). Abhängig vom System, der Version von Matlab, der Größe der Variablen und genau dem, was sich in den Schleifen befindet, ist es nicht immer schneller JIT zu verwenden. Dies hängt mit dem "Aufwärmen" -Effekt zusammen, bei dem manchmal, wenn Sie eine m-Datei mehr als einmal in einer Sitzung ausführen, sie nach dem ersten Durchlauf schneller wird, da der Beschleuniger nur einige Teile des Codes einmal kompilieren muss.

JIT (Funktion Accel auf)

Elapsed time is 0.176765 seconds. 
Elapsed time is 0.185301 seconds. 

Elapsed time is 0.252631 seconds. 
Elapsed time is 0.284415 seconds. 

Elapsed time is 1.782446 seconds. 
Elapsed time is 0.693508 seconds. 

Elapsed time is 0.855005 seconds. 
Elapsed time is 1.004955 seconds. 

JIT aus (Feature Accel off)

Elapsed time is 0.143924 seconds. 
Elapsed time is 0.184360 seconds. 

Elapsed time is 0.206405 seconds. 
Elapsed time is 0.306424 seconds. 

Elapsed time is 1.416654 seconds. 
Elapsed time is 2.718846 seconds. 

Elapsed time is 2.110420 seconds. 
Elapsed time is 4.027782 seconds. 

ETA, irgendwie interessant zu sehen, was passiert, wenn Sie ganze Zahlen anstelle von Doppel verwenden passiert:

JIT ein, gleicher Code aber konvertiert x mit int8

Elapsed time is 0.202201 seconds. 
Elapsed time is 0.192103 seconds. 

Elapsed time is 0.294974 seconds. 
Elapsed time is 0.296191 seconds. 

Elapsed time is 2.001245 seconds. 
Elapsed time is 2.038713 seconds. 

Elapsed time is 0.870500 seconds. 
Elapsed time is 0.898301 seconds. 

JIT aus, int8

Elapsed time is 0.198611 seconds. 
Elapsed time is 0.187589 seconds. 

Elapsed time is 0.282775 seconds. 
Elapsed time is 0.282938 seconds. 

Elapsed time is 1.837561 seconds. 
Elapsed time is 1.846766 seconds. 

Elapsed time is 2.746034 seconds. 
Elapsed time is 2.760067 seconds. 
+0

Es ist interessant zu sehen, dass das Ausschalten des JIT es tatsächlich schneller macht. Wenn das Aufwärmen jedoch das Problem wäre, würde dies nicht erklären, warum 100000 langsamer als 150000 ist. Beachten Sie, dass es auch passiert, wenn Sie die Reihenfolge 'N = [10000 15000 150000 100000]' –

+0

ändern. Ich denke nicht, dass das Aufwärmen funktioniert in der Befehlszeile. Ich rate im Grunde, dass es einen Overhead für die Verwendung von JIT gibt, der eine Funktion der variablen Größe sein kann, und einen gewissen Nutzen, der auch eine Funktion der variablen Größe ist. Schließlich ist der Nutzen größer als der Overhead, aber nicht bis zu Größen von x> 150000 oder so (in diesem Fall). – nkjt

+0

Es kann nicht wirklich von der JIT kommen - bitte sehen Sie meine Antwort. – marsei

Verwandte Themen