Effizienter Weg, um die Kräfte eines Vektors zu nutzen

8

Ich habe einen Code geschrieben, der numerisch Legendre-Polynome bis zu einer hohen n-ten Ordnung verwendet. Zum Beispiel:

%Vor%

Wenn der Vektor x lang ist, kann dies langsam werden. Ich habe gesehen, dass es einen Leistungsunterschied zwischen sagen x.^4 und x.*x.*x.*x gibt und dachte, ich könnte dies verwenden, um meinen Code zu verbessern. Ich habe timeit verwendet und folgendes gefunden:

%Vor%

f4 ist schneller um einen Faktor 2 als der Rest. Wenn ich jedoch zu x.^6 gehe, gibt es einen sehr geringen Unterschied zwischen (x.*x.*x).^2 und x.*x.*x.*x.*x.*x (während alle anderen Optionen langsamer sind).

Gibt es einen Weg, um zu sagen, wie der Vektor am effizientesten genutzt werden kann? Können Sie erklären, warum es so große Unterschiede in der Leistung gibt?

    
Luis Mendo 24.09.2013, 23:06
quelle

3 Antworten

8

Dies ist nicht genau eine Antwort auf Ihre Frage, aber es kann Ihr Problem lösen:

%Vor%

Auf diese Weise machst du die Kraft nur einmal und nur mit Exponent 2. Dieser Trick kann auf alle Legendre-Polynome angewendet werden (in den ungeraden Polynomen wird ein x2 durch x ersetzt).

    
Luis Mendo 24.09.2013, 23:48
quelle
1

Hier sind einige Gedanken:

power(x,4) und x.^4 sind äquivalent (lesen Sie einfach das Dokument).

x.*x.*x.*x ist wahrscheinlich auf etwas wie x.^2.^2

optimiert

x.^2.^2 wird wahrscheinlich wie folgt berechnet: Nimm das Quadrat jedes Elements (schnell) und nimm das Quadrat davon (schnell wieder).

x.^4 wird wahrscheinlich direkt ausgewertet als: Nimm die vierte Potenz jedes Elements (langsam).

Es ist nicht so seltsam zu sehen, dass 2 schnelle Operationen weniger Zeit benötigen als 1 langsame Operation. Schade nur, dass die Optimierung nicht im Power 4-Fall durchgeführt wird, aber vielleicht wird es nicht immer funktionieren oder mit Kosten verbunden sein (Eingabeüberprüfung, Speicher?).

Über die Zeiten: Eigentlich gibt es viel mehr Unterschied als ein Faktor 2!

Wenn Sie sie jetzt in einer Funktion aufrufen, wird der Funktionsoverhead in jedem Fall hinzugefügt, wodurch die relativen Unterschiede kleiner werden:

%Vor%

gibt Folgendes:

%Vor%

Es ist also fast ein Unterschied von Faktor 10. Beachten Sie jedoch, dass der Zeitunterschied in Sekunden immer noch gering ist. Daher würde ich für die meisten praktischen Anwendungen nur die einfache Syntax verwenden.

    
Dennis Jaheruddin 25.09.2013 14:21
quelle
1

Es scheint so, als ob Mathworks spezielle verkleinerte Quadrate in seiner Potenzfunktion hat (leider ist alles in einer geschlossenen Quelle eingebaut, die wir nicht sehen können). In meinem Test auf R2013b scheint es, als ob .^ , power und realpow denselben Algorithmus verwenden. Für Quadrate, ich glaube, sie haben spezielle-cased es x.*x .

%Vor%

Für Würfel ist die Geschichte anders. Sie sind nicht mehr speziell verpackt. Auch hier sind .^ , power und realpow alle ähnlich, aber diesmal viel langsamer:

%Vor%

Lassen Sie uns zur 16. Potenz springen, um zu sehen, wie diese Algorithmen skalieren:

%Vor%

Also: .^ , power und realpow alle laufen in einer konstanten Zeit in Bezug auf den Exponenten, außer es wurde speziell verkettet (-1 scheint auch speziell umkleidet zu sein). Die Verwendung des exp(n*log(x)) Tricks ist auch eine konstante Zeit in Bezug auf den Exponenten und schneller. Das einzige Ergebnis, das ich nicht ganz verstehe, ist, warum das wiederholte Quadrieren langsamer ist als die Multiplikation.

Wie erwartet, erhöht die Vergrößerung von x um den Faktor 100 die Zeit für alle Algorithmen gleichermaßen.

Also, Moral der Geschichte? Wenn Sie skalare Integer-Exponenten verwenden, führen Sie die Multiplikation immer selbst durch. In power und Freunden gibt es eine Menge Schlau (der Exponent kann Fließkomma, Vektor usw. sein). Die einzigen Ausnahmen sind, wo Mathworks die Optimierung für Sie vorgenommen hat. In 2013b scheint es x^2 und x^(-1) zu sein. Hoffentlich werden sie mit der Zeit mehr hinzufügen. Aber im Allgemeinen ist die Potenzierung schwierig und die Multiplikation ist einfach. Im leistungssensitiven Code glaube ich nicht, dass Sie Fehler machen können, indem Sie immer x.*x.*x.*x eingeben. (Natürlich, in Ihrem Fall, folgen Sie Luis Ratschlag und nutzen Sie die Zwischenergebnisse innerhalb jedes Semesters!)

%Vor%     
Matt B. 25.09.2013 14:52
quelle

Tags und Links