Porównywałem kilka moich kodów z „zapasowymi” kodami MATLAB. Jestem zaskoczony wynikami.
Uruchomiłem przykładowy kod (Sparse Matrix)
n = 5000;
a = diag(rand(n,1));
b = rand(n,1);
disp('For a\b');
tic;a\b;toc;
disp('For LU');
tic;LULU;toc;
disp('For Conj Grad');
tic;conjgrad(a,b,1e-8);toc;
disp('Inv(A)*B');
tic;inv(a)*b;toc;
Wyniki:
For a\b
Elapsed time is 0.052838 seconds.
For LU
Elapsed time is 7.441331 seconds.
For Conj Grad
Elapsed time is 3.819182 seconds.
Inv(A)*B
Elapsed time is 38.511110 seconds.
W przypadku gęstej matrycy:
n = 2000;
a = rand(n,n);
b = rand(n,1);
disp('For a\b');
tic;a\b;toc;
disp('For LU');
tic;LULU;toc;
disp('For Conj Grad');
tic;conjgrad(a,b,1e-8);toc;
disp('For INV(A)*B');
tic;inv(a)*b;toc;
Wyniki:
For a\b
Elapsed time is 0.575926 seconds.
For LU
Elapsed time is 0.654287 seconds.
For Conj Grad
Elapsed time is 9.875896 seconds.
Inv(A)*B
Elapsed time is 1.648074 seconds.
Jak do cholery jest tak niesamowicie?
linear-algebra
performance
matlab
Śledztwo
źródło
źródło
Odpowiedzi:
W Matlabie komenda „\” wywołuje algorytm, który zależy od struktury macierzy A i obejmuje sprawdzenie (mały narzut) właściwości A.
Aby zmniejszyć koszty ogólne, można użyć polecenia linsolve w Matlabie i wybrać odpowiedni solver spośród tych opcji.
źródło
Jeśli chcesz zobaczyć, co
a\b
robi dla twojej konkretnej matrycy, możesz ustawićspparms('spumoni',1)
i dokładnie określić, jakim algorytmem byłeś pod wrażeniem. Na przykład:wyjdzie
więc widzę, że w tym przypadku „\” użyło „CHOLMOD”.
źródło
help mldivide
.W przypadku rzadkich macierzy Matlab używa UMFPACK do operacji „
\
”, która w twoim przykładzie zasadniczo przegląda wartościa
, odwraca je i mnoży je przez wartościb
. Jednak w tym przykładzie powinieneś użyćb./diag(a)
, który jest znacznie szybszy.W przypadku gęstych systemów operator odwrotnego ukośnika jest nieco bardziej skomplikowany. Krótki opis tego, co się dzieje, gdy jest podany tutaj . Zgodnie z tym opisem, w twoim przykładzie Matlab rozwiązałby
a\b
za pomocą podstawienia wstecznego. W przypadku ogólnych macierzy kwadratowych stosuje się rozkład LU.źródło
tic; for k=1:100, a\b; end; toc
.Zasadniczo, jeśli masz rzadką matrycę o rozsądnej złożoności (tj. Nie musi to być szablon 5-punktowy, ale w rzeczywistości może być dyskretyzacją równań Stokesa, dla których liczba niezerowych w rzędzie wynosi znacznie większy niż 5), wówczas rzadki bezpośredni solver, taki jak UMFPACK, zazwyczaj pokonuje iteracyjny solver Kryłowa, jeśli problem nie jest większy niż około 100 000 niewiadomych.
Innymi słowy, dla większości rzadkich macierzy wynikających z dyskretyzacji 2D, najszybszym rozwiązaniem jest bezpośredni solver. Tylko w przypadku problemów 3D, w których szybko dostajesz ponad 100 000 niewiadomych, konieczne jest użycie iteracyjnego solvera.
źródło