Wie kann ich diesen Aufruf zum Quantil in Matlab beschleunigen?

8

Ich habe eine MATLAB-Routine mit einem offensichtlichen Engpass. Ich habe die Funktion profiliert, mit dem Ergebnis, dass in der Funktion levels : 2/3 der Rechenzeit verwendet wird:

Die Funktion levels verwendet eine Float-Matrix und teilt jede Spalte in nLevels Buckets auf und gibt eine Matrix derselben Größe wie die Eingabe zurück, wobei jeder Eintrag durch die Nummer des Buckets ersetzt wird, in den er fällt.

Dazu benutze ich die Funktion quantile , um die Bucket-Limits zu erhalten, und eine Schleife, um die Einträge den Buckets zuzuweisen. Hier ist meine Implementierung:

%Vor%

Gibt es etwas, was ich tun kann, um das zu beschleunigen? Kann der Code vektorisiert werden?

    
Chris Taylor 22.12.2011, 09:22
quelle

5 Antworten

4

Wenn ich richtig verstehe, willst du wissen, wie viele Gegenstände in jedem Eimer gefallen sind. Verwenden Sie:

  

n = hist (Y, nbins)

Obwohl ich nicht sicher bin, dass es bei der Beschleunigung helfen wird. Es ist einfach sauberer.

Bearbeiten: Nach dem Kommentar:

Sie können den zweiten Ausgabeparameter von histc

verwenden
  

[n, bin] = histc (...) gibt auch eine Indexmatrix zurück. Wenn x ein Vektor ist, ist n (k) = & gt; sum (bin == k). bin für Werte außerhalb des Bereichs null. Wenn x eine M-mal-N-Matrix ist, dann

    
Andrey Rubshtein 22.12.2011, 09:50
quelle
2

Wie steht es damit?

%Vor%

Dies führt zu folgendem:

%Vor%

Sie können auch die Logik ändern, um sicherzustellen, dass die Werte kleiner als der Anfang der nächsten Bin sind. Ich glaube jedoch nicht, dass es notwendig ist.

    
Aero Engy 22.12.2011 13:33
quelle
2

Ich denke du solltest histc

verwenden

[~,Y] = histc(X,q)

Wie Sie in Matlabs Dokument sehen können:

  

Beschreibung

     

n = histc (x, Kanten) zählt die Anzahl der fallenden Werte im Vektor x   zwischen den Elementen im Kantenvektor (der enthalten muss   monoton nicht abnehmende Werte). n ist ein Längen- (Kanten-) Vektor   enthält diese Zählungen. Keine Elemente von x können komplex sein.

    
Oli 22.12.2011 09:51
quelle
1

Ich habe ein paar Verfeinerungen (darunter eine von Aero Engy in einer anderen Antwort) gemacht, die zu einigen Verbesserungen geführt haben. Um sie zu testen, habe ich eine zufällige Matrix von einer Million Zeilen und 100 Spalten erstellt, um die verbesserten Funktionen auszuführen:

%Vor%

Zuerst habe ich meinen unmodifizierten Code mit den folgenden Ergebnissen ausgeführt:

Beachten Sie, dass von den 40 Sekunden ungefähr 14 davon für die Berechnung der Quantile verwendet werden - ich kann nicht erwarten, diesen Teil der Routine zu verbessern (ich nehme an, dass Mathworks es bereits optimiert hat, obwohl ich vermute, dass es ein macht ...)

Als nächstes änderte ich die Routine auf die folgende, die schneller sein sollte und den Vorteil hat, weniger Linien zu sein!

%Vor%

Die Profilergebnisse mit diesem Code lauten:

Es ist also 15 Sekunden schneller, was eine 150% ige Beschleunigung des Teils meines Codes und nicht von MathWorks bedeutet.

Nach einem Vorschlag von Andrey (wieder in einer anderen Antwort) habe ich den Code geändert, um die zweite Ausgabe der Funktion histc zu verwenden, die den Bins Einträge zuweist. Es behandelt die Spalten nicht unabhängig voneinander, also musste ich die Spalten manuell durchlaufen, aber es scheint sehr gut zu funktionieren. Hier ist der Code:

%Vor%

Und die Profilergebnisse:

Wir geben jetzt nur 4,3 Sekunden in Codes außerhalb der Funktion quantile aus, was eine Beschleunigung von 500% gegenüber dem ist, was ich ursprünglich geschrieben habe. Ich habe ein bisschen Zeit damit verbracht, diese Antwort zu schreiben, weil ich denke, dass es ein schönes Beispiel dafür ist, wie Sie den MATLAB-Profiler und StackExchange in Kombination verwenden können, um eine bessere Leistung Ihres Codes zu erzielen.

Ich bin glücklich mit diesem Ergebnis, obwohl ich natürlich weiterhin gerne andere Antworten hören werde. In diesem Stadium wird der Hauptleistungszuwachs durch die Erhöhung der Leistung des Teils des Codes erzielt, der momentan quantile aufruft. Ich kann nicht sofort sehen, wie das geht, aber vielleicht kann jemand anderes hier. Nochmals vielen Dank!

    
Chris Taylor 22.12.2011 14:08
quelle
1

Sie können sort die Spalten und teilen + runden die inversen Indizes:

%Vor%

Oder Sie können tiedrank :

verwenden %Vor%

Überraschenderweise sind beide Lösungen etwas langsamer als die quantile + histc Lösung.

    
cyborg 22.12.2011 14:18
quelle