Ich arbeite mit Matlab.
Ich habe eine binäre quadratische Matrix. Für jede Zeile gibt es einen oder mehrere Einträge von 1. Ich möchte jede Zeile dieser Matrix durchgehen und den Index dieser Einsen zurückgeben und sie im Eintrag einer Zelle speichern.
Ich habe mich gefragt, ob es eine Möglichkeit gibt, dies zu tun, ohne alle Zeilen dieser Matrix zu durchlaufen, da die Schleife in Matlab sehr langsam ist.
Zum Beispiel meine Matrix
M = 0 1 0
1 0 1
1 1 1
Dann will ich irgendwann so etwas
A = [2]
[1,3]
[1,2,3]
So A
ist eine Zelle.
Gibt es eine Möglichkeit, dieses Ziel ohne for-Schleife zu erreichen, um das Ergebnis schneller zu berechnen?
matlab
vectorization
ftxx
quelle
quelle
for
Schleifen vermeidet ? Für dieses Problem vermute ich bei modernen Versionen von MATLAB stark, dass einefor
Schleife die schnellste Lösung ist. Wenn Sie ein Leistungsproblem haben, suchen Sie vermutlich am falschen Ort nach einer Lösung, die auf veralteten Ratschlägen basiert.cellfun
.1
s in einer typischen Reihe? Ich würde nicht erwarten, dass einefind
Schleife etwas in der Nähe von 30 Sekunden benötigt, damit etwas klein genug ist, um in den physischen Speicher zu passen.Antworten:
Am Ende dieser Antwort steht ein Benchmarking-Code, da Sie klargestellt haben, dass Sie an Leistung interessiert sind, anstatt
for
Schleifen willkürlich zu vermeiden .Tatsächlich denke ich, dass
for
Loops hier wahrscheinlich die performanteste Option sind. Seit Einführung der "neuen" (2015b) JIT-Engine sind ( Quell- )for
Schleifen nicht von Natur aus langsam - tatsächlich werden sie intern optimiert.Sie können dem Benchmark
mat2cell
entnehmen, dass die von ThomasIsCoding hier angebotene Option sehr langsam ist ...Wenn wir diese Linie
splitapply
entfernen , um die Skala klarer zu machen, ist meine Methode ziemlich langsam. Obchardons Accumarray-Option ist etwas besser, aber die schnellsten (und vergleichbaren) Optionen verwenden entwederarrayfun
(wie auch von Thomas vorgeschlagen) oder einefor
Schleife. Beachten Sie, dass dies für die meisten Anwendungsfälle imarrayfun
Grunde genommen einefor
verschleierte Schleife ist. Dies ist also keine überraschende Verbindung!Ich würde empfehlen, einefor
Schleife zu verwenden, um die Lesbarkeit des Codes und die beste Leistung zu verbessern.Bearbeiten :
Wenn wir davon ausgehen, dass das Schleifen der schnellste Ansatz ist, können wir einige Optimierungen am
find
Befehl vornehmen .Speziell
Machen Sie
M
logisch. Wie das folgende Diagramm zeigt, kann dies für relativ kleine Personen schneller seinM
, jedoch langsamer, wenn die Typkonvertierung für große Geräte abgewogen wirdM
.Verwenden Sie eine Logik,
M
um ein Array zu indizieren,1:size(M,2)
anstatt es zu verwendenfind
. Dies vermeidet den langsamsten Teil der Schleife (denfind
Befehl) und überwiegt den Typkonvertierungsaufwand, was ihn zur schnellsten Option macht.Hier ist meine Empfehlung für die beste Leistung:
Ich habe dies dem unten stehenden Benchmark hinzugefügt. Hier ist der Vergleich von Loop-Ansätzen:
Benchmarking-Code:
quelle
M
. Wenn zum Beispiel nur 5% der Elemente gefüllt sind,M = randi([0,20],N) == 20;
ist diefor
Schleife bei weitem die langsamste und Ihrearrayfun
Methode gewinnt.accumarray
ohne gewesenind2sub
, aber er ist langsamer als diefor
SchleifeSie können
arrayfun
wie unten versuchen , die durch Reihen von fegenM
oder (ein langsamerer Ansatz von
mat2cell
)quelle
arrayfun
es sich im Grunde genommen um eine Loop-in-Verkleidung handelt, kann dies an beiden Fronten fehlschlagen: 1) Vermeidung von Loops und 2) Schnelligkeit, wie vom OP erhofftBearbeiten : Ich habe einen Benchmark hinzugefügt. Die Ergebnisse zeigen, dass eine for-Schleife effizienter ist als
accumarray
.Sie können verwenden
find
undaccumarray
:Die Matrix wird transponiert (
A'
), weilfind
nach Spalten gruppiert.Beispiel:
Ausgabe:
Benchmark:
Ergebnis:
Eine for-Schleife ist effizienter als
accumarray
...quelle
Mit accumarray :
quelle
MM{I} = find(M(I, :))
.ind2sub
:[ii, jj] = find(M); accumarray(ii, jj, [], @(x){x})
Sie können strfind verwenden :
quelle
string
Typen anstelle von Zeichen verwendet würden? Es gibt viele Optimierungen für Saiten, daher gibt es sie auch ...