Meine Frage: Ich habe festgestellt, dass viele gute Antworten auf Matlab-Fragen zu SO häufig die Funktion verwenden bsxfun
. Warum?
Motivation: In der Matlab-Dokumentation für bsxfun
finden Sie das folgende Beispiel:
A = magic(5);
A = bsxfun(@minus, A, mean(A))
Natürlich könnten wir den gleichen Vorgang ausführen mit:
A = A - (ones(size(A, 1), 1) * mean(A));
Tatsächlich zeigt ein einfacher Geschwindigkeitstest, dass die zweite Methode etwa 20% schneller ist. Warum also die erste Methode anwenden? Ich vermute, es gibt einige Umstände, unter denen die Verwendung bsxfun
viel schneller ist als der "manuelle" Ansatz. Es würde mich wirklich interessieren, ein Beispiel für eine solche Situation und eine Erklärung zu sehen, warum es schneller ist.
Ein letztes Element zu dieser Frage, ebenfalls aus der Matlab-Dokumentation für bsxfun
: "C = bsxfun (fun, A, B), wendet die Element-für-Element-Binäroperation, die durch das Funktionshandle fun angegeben ist, auf Arrays A und B mit Singleton an Erweiterung aktiviert. ". Was bedeutet der Ausdruck "mit aktivierter Singleton-Erweiterung"?
tic...toc
um die Zeilen setzen, hängt die Geschwindigkeit des Codes davon ab, dass Funktionen in den Speicher eingelesen werden müssen.timeit
Funktion in dem Link gelesen habe, den Sie / Angainor / Dan bereitstellen.Antworten:
Ich benutze drei Gründe
bsxfun
( Dokumentation , Blog-Link )bsxfun
ist schneller alsrepmat
(siehe unten)bsxfun
erfordert weniger Eingabebsxfun
wie mit benutzeaccumarray
, fühle ich mich gut mit meinem Verständnis von Matlab.bsxfun
repliziert die Eingabearrays entlang ihrer "Singleton-Dimensionen", dh der Dimensionen, entlang derer die Größe des Arrays 1 ist, so dass sie mit der Größe der entsprechenden Dimension des anderen Arrays übereinstimmen. Dies wird als "Singleton-Expasion" bezeichnet. Abgesehen davon sind die Singleton-Dimensionen diejenigen, die gelöscht werden, wenn Sie anrufensqueeze
.Es ist möglich, dass bei sehr kleinen Problemen der
repmat
Ansatz schneller ist - aber bei dieser Arraygröße sind beide Vorgänge so schnell, dass es wahrscheinlich keinen Unterschied in Bezug auf die Gesamtleistung macht. Es gibt zwei wichtige Gründe,bsxfun
die schneller sind: (1) Die Berechnung erfolgt in kompiliertem Code, was bedeutet, dass die tatsächliche Replikation des Arrays niemals stattfindet, und (2)bsxfun
ist eine der Multithread-Matlab-Funktionen.Ich habe einen Geschwindigkeitsvergleich zwischen
repmat
undbsxfun
mit R2012b auf meinem anständig schnellen Laptop durchgeführt.Für mich
bsxfun
ist das ca. 3 mal schneller alsrepmat
. Der Unterschied wird stärker, wenn die Arrays größer werdenDer Laufzeitsprung von
repmat
erfolgt bei einer Arraygröße von 1 MB, was möglicherweise etwas mit der Größe meines Prozessor-Cache zu tun hat.bsxfun
Ein Sprung wird nicht so schlimm, da nur das Ausgabearray zugewiesen werden muss.Unten finden Sie den Code, den ich für das Timing verwendet habe:
quelle
In meinem Fall verwende ich,
bsxfun
weil ich nicht über Spalten- oder Zeilenprobleme nachdenken muss.Um Ihr Beispiel zu schreiben:
Ich muss mehrere Probleme lösen:
1)
size(A,1)
odersize(A,2)
2)
ones(sizes(A,1),1)
oderones(1,sizes(A,1))
3)
ones(size(A, 1), 1) * mean(A)
odermean(A)*ones(size(A, 1), 1)
4)
mean(A)
odermean(A,2)
Wenn ich benutze
bsxfun
, muss ich nur den letzten lösen:a)
mean(A)
odermean(A,2)
Du denkst vielleicht, es ist faul oder so, aber wenn ich es benutze
bsxfun
, habe ich weniger Fehler und programmiere schneller .Darüber hinaus ist es kürzer, was die Schreibgeschwindigkeit und Lesbarkeit verbessert .
quelle
Sehr interessante Frage! Ich bin kürzlich bei der Beantwortung dieser Frage auf genau diese Situation gestoßen . Betrachten Sie den folgenden Code, der Indizes eines Schiebefensters der Größe 3 durch einen Vektor berechnet
a
:In diesem Fall
bsxfun
ist fast doppelt so schnell! Es ist nützlich und schnell, da es die explizite Zuweisung von Speicher für Matrizen vermeidetidx0
undidx1
diese im Speicher speichert und sie dann erneut liest, um sie hinzuzufügen. Da die Speicherbandbreite ein wertvolles Gut und häufig der Engpass bei heutigen Architekturen ist, möchten Sie sie mit Bedacht einsetzen und den Speicherbedarf Ihres Codes verringern, um die Leistung zu verbessern.bsxfun
Damit können Sie genau das tun: Erstellen Sie eine Matrix, die auf der Anwendung eines beliebigen Operators auf alle Elementpaare zweier Vektoren basiert, anstatt explizit auf zwei Matrizen zu arbeiten, die durch Replizieren der Vektoren erhalten werden. Das ist Singleton-Erweiterung . Sie können es sich auch als das äußere Produkt von BLAS vorstellen:Sie multiplizieren zwei Vektoren, um eine Matrix zu erhalten. Nur dass das äußere Produkt nur eine Multiplikation durchführt und
bsxfun
beliebige Operatoren anwenden kann. Nebenbei bemerkt ist es sehr interessant zu sehen, dassbsxfun
das so schnell ist wie das BLAS-Außenprodukt. Und BLAS ist in der Regel betrachtet liefert die Leistung ..Bearbeiten Dank Dans Kommentar ist hier ein großartiger Artikel von Loren , der genau das bespricht.
quelle
bsxfun
mit einem guten Beispiel klar ausdrückt.Ab R2016b unterstützt Matlab die implizite Erweiterung für eine Vielzahl von Operatoren, sodass in den meisten Fällen nicht mehr Folgendes erforderlich ist
bsxfun
:Es gibt eine ausführliche Diskussion von Implicit Expansion und seine Leistung auf Loren Blog. Um Steve Eddins von MathWorks zu zitieren :
quelle
Die Dinge stimmen nicht immer mit den drei gängigen Methoden
repmat
überein : Expension by One Indexing undbsxfun
. Interessanter wird es, wenn Sie die Vektorgröße noch weiter erhöhen. Siehe Handlung:bsxfun
wird tatsächlich irgendwann etwas langsamer als die beiden anderen, aber was mich überrascht hat, ist, dass bsxfun plötzlich wieder um etwa das Dreifache schneller wird, wenn Sie die Vektorgröße noch weiter erhöhen (> 13E6 Ausgabeelemente). Ihre Geschwindigkeiten scheinen schrittweise zu springen und die Reihenfolge ist nicht immer konsistent. Ich vermute, es könnte auch von der Prozessor- / Speichergröße abhängen, aber im Allgemeinen denke ich, dass ich mich,bsxfun
wann immer möglich, daran halten würde.quelle