Wiederholtes Lösen von

12

Ich verwende MATLAB, um ein Problem zu lösen, bei dem zu jedem Zeitpunkt gelöst wird, wobei sich mit der Zeit ändert. Im Moment mache ich das mit MATLABs :Ax=bbmldivide

x = A\b

Ich habe die Flexibilität, so viele Vorberechnungen wie nötig durchzuführen, und frage mich, ob es eine schnellere und / oder genauere Methode als gibt mldivide. Was wird hier typischerweise gemacht? Vielen Dank an alle!

Zweifel
quelle
1
Haben Sie spezielle Kenntnisse über die Struktur von ? Ist es zum Beispiel symmetrisch? Positiv bestimmt? Tridiagonal? Senkrecht? A
Dominique
Die Matrix ist eine dichte quadratische Matrix. A
Zweifel
3
Wenn Sie keine weiteren Kenntnisse über , ist die Faktorisierung, wie in der Antwort unten beschrieben, die beste Wahl. L UALU
Dominique

Antworten:

14

Das offensichtlichste, was Sie tun können, ist die Vorausberechnung

[L,U] = lu(A) ~ O (n ^ 3)

Dann rechnest du einfach

x = U \ (L \ b) ~ O (2 n ^ 2)

Dies würde die Kosten enorm senken und beschleunigen. Die Genauigkeit wäre gleich.

Milind R
quelle
1
Aus der Dokumentation geht hervor , dass L nicht unbedingt ein unteres Dreieck ist. Diese Antwort wäre wahrscheinlich schneller als eine direkte Lösung. Ich würde jedoch sorgfältig darauf achten, dass der Befehl L \ b intelligent genug ist, um L in der richtigen Reihenfolge zu lösen (dies ist wahrscheinlich, aber nicht mit Sicherheit der Fall) in der Dokumentation).
Godric Seer
Ja, Sie haben recht, L ist das Produkt einer unteren Dreiecksmatrix und einer Permutationsmatrix. Aber ich werde verdammt sein, wenn es nicht erkennt, dass alles, was es zu tun hat, die Substitution mit rückwärts ist L\b. Weil ich gesehen habe, dass genau diese Zeile von denjenigen, die ich für Experten halte, im Hochleistungscode verwendet wird.
Milind R
8
mldivide erkennt permutierte Dreiecksmatrizen und löst ein solches System mit dem richtigen . In meinen Experimenten scheint dies den Lösungsprozess für eine Matrix der Größe 2000 um etwa den Faktor 10 von 2000 auf 10000 von 10000 zu verlangsamen. Daher ist es besser, die Permutation explizit mit [L , U, P] = lu (P). O(n2)
Brian Borchers
1
Wenn Ihre Matrix spärlich ist, sollten Sie die Sparsamkeit beim Lösen des Systems ausnutzen. Der einfachste Weg, dies zu tun, besteht darin, sicherzustellen, dass im Sparse-Format gespeichert ist, indem A = Sparse (A) verwendet wird, bevor die LU-Faktorisierung berechnet wird. Sie können auch versuchen, die Zeilen von A zu permutieren, um das Ausfüllen während der LU-Faktorisierung zu verringern. A
Brian Borchers
3
@BrianBorcher Soweit ich weiß, ist der beste Weg, die Permutation im Auge zu behalten, [L,U,p] = lu(A,'vector'); x = U\(L\b(p));Beispiel 3 in den lu Dokumenten .
Stefano M
5

Zu diesem Thema haben wir in unseren Kursen zum wissenschaftlichen Rechnen einige umfangreiche Computerlabore durchgeführt. Für die "kleinen" Berechnungen, die wir dort durchgeführt haben, war der Backslash-Operator von Matlab immer schneller als alles andere, auch nachdem wir unseren Code so weit wie möglich optimiert und alle Matrizen zuvor neu angeordnet hatten (zum Beispiel mit der Bestellung von Reverse Cuthill McKee für dünne Matrizen). .

Sie können eine unserer Laboranweisungen lesen . Die Antwort auf Ihre Frage wird (in Kürze) auf Seite 4 behandelt.

Ein gutes Buch zu diesem Thema wurde zum Beispiel von Cheney geschrieben .

seb
quelle
4

Angenommen, ist eine n × n dichte Matrix und Sie müssen A x i = b i , i = 1 m lösen . Wenn m ist groß genug , dann gibt es nichts falsch inAn×n Axi=bii=1mm

V = inv(A);
...
x = V*b;

Flops sind für und O ( n 2 ) für , daher sind einige Experimente erforderlich , um den Break-Even-Wert für m zu bestimmen ...O(n3)inv(A)O(n2)V*bm

>> n = 5000;
>> A = randn(n,n);
>> x = randn(n,1);
>> b = A*x;
>> rcond(A)
ans =
   1.3837e-06
>> tic, xm = A\b; toc
Elapsed time is 1.907102 seconds.
>> tic, [L,U] = lu(A); toc
Elapsed time is 1.818247 seconds.
>> tic, xl = U\(L\b); toc
Elapsed time is 0.399051 seconds.
>> tic, [L,U,p] = lu(A,'vector'); toc
Elapsed time is 1.581756 seconds.
>> tic, xp = U\(L\b(p)); toc
Elapsed time is 0.060203 seconds.
>> tic, V=inv(A); toc
Elapsed time is 7.614582 seconds.
>> tic, xv = V*b; toc     
Elapsed time is 0.011499 seconds.
>> [norm(xm-x), norm(xp-x), norm(xl-x), norm(xv-x)] ./ norm(x)
ans =
   1.0e-11 *
    0.1912    0.1912    0.1912    0.6183

A1LUm>125

Einige Notizen

Informationen zur Stabilität und Fehleranalyse finden Sie in den Kommentaren zu dieser anderen Antwort , insbesondere der von VictorLiu.

mn

Das Timing wurde mit Matlab R2011b auf einem 12-Kern-Computer mit einem ziemlich konstanten UNIX-Lastdurchschnitt von 5 durchgeführt. beste tic, tocZeit von drei Sonden.

Stefano M
quelle
Tatsächlich ist in einem Matrixvektor-Multiplikator weitaus mehr Parallelität verfügbar als in einem Dreieckslöser. Dies sollte also noch deutlicher erkennbar sein, wenn die Berechnungen in irgendeiner Weise parallel erfolgen (Multicore / GPU / etc ...).
Aron Ahmadia
@AronAhmadia Ich stimme zu: Break-Even-Punkt-Schätzungen, die nur auf der Anzahl der Vorgänge basieren, sind nur für eine serielle Implementierung sinnvoll.
Stefano M
1
Beachten Sie, dass sich die Dinge erheblich unterscheiden, wenn die A-Matrix dünn ist - die Inverse ist normalerweise ziemlich dicht, während die LU-Faktoren normalerweise ziemlich dünn sind und die Dinge in Richtung der LU zurückkippen, was schneller ist.
Brian Borchers
1
A
1
inv(A)Ax=bbBA\B
2

Werfen Sie einen Blick auf diese Frage , die Antworten zeigen, dass sie mldivideziemlich clever ist, und geben Sie auch Vorschläge, wie Sie sehen können, was Matlab zur Lösung verwendet A\b. Dies kann Ihnen einen Hinweis zu den Optimierungsoptionen geben.

Psirus
quelle
0

Die Verwendung von Backslash ist mehr oder weniger gleichbedeutend mit inv(A)*Bder intuitiven Codierung. Sie sind ungefähr gleich (nur in der Art und Weise, wie die Berechnung durchgeführt wird), obwohl Sie die Matlab-Dokumentation zur Verdeutlichung überprüfen sollten.

Um Ihre Frage zu beantworten, ist Backslash im Allgemeinen in Ordnung, es hängt jedoch von den Eigenschaften der Massenmatrix ab.

AlanH
quelle
1
Mathematisch ist inv (A) * b dasselbe wie \, jedoch ist die tatsächliche Bildung der Inversen weniger effizient und weniger genau. Wenn Sie daran arbeiten, die lineare Algebra zu lernen, mag dies akzeptabel sein, aber ich würde behaupten, Sie brauchen einen sehr guten Grund, um die Inverse zu bilden.
Godric Seer
Aber warum würden Sie jemals rechnen, inv(A)da dies allein teurer ist als A\b?
Dominique
7
@Godric: In einem kürzlich erschienenen Artikel wird der "Mythos" diskutiert, dass inv (A) * b weniger genau ist: auf ArXiv . Das heißt nicht, dass es normalerweise einen Grund gibt, die tatsächliche Inverse zu berechnen, sondern nur zu sagen.
Victor Liu
3
@Dominique: Dreieckslösungen sind viel weniger parallelisierbar als die Matrix-Vektor-Multiplikation, und anspruchsvolle vorkonditionierte iterative Methoden verwenden häufig direkte Methoden für Unterdomänen. Es ist oft nützlich, die Inversen einiger kleinerer dichter Dreiecksmatrizen explizit zu bilden, um die Parallelität zu verbessern.
Jack Poulson
@ VictorLiu: Vielen Dank für den Artikel. Ich stehe korrigiert auf meiner Genauigkeitsangabe (zumindest für smarte Implementierungen von inv (A)).
Godric Seer