Eu estava comparando alguns dos meus códigos com os códigos "estoque" do MATLAB. Estou surpreso com os resultados.
Corri um código de exemplo (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;
Resultados :
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.
Para matriz densa:
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;
Resultados:
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.
Como diabos é tão impressionante?
linear-algebra
performance
matlab
Inquérito
fonte
fonte
Respostas:
No Matlab, o comando '\' invoca um algoritmo que depende da estrutura da matriz A e inclui verificações (pequenas despesas gerais) nas propriedades de A.
Para reduzir a sobrecarga, é possível usar o comando linsolve no Matlab e selecionar um solucionador adequado entre essas opções.
fonte
Se você quiser ver o que
a\b
faz para sua matriz em particular, pode definirspparms('spumoni',1)
e descobrir exatamente qual algoritmo ficou impressionado. Por exemplo:irá produzir
para que eu possa ver que "\" acabou usando "CHOLMOD" nesse caso.
fonte
help mldivide
.Para matrizes esparsas, o Matlab usa UMFPACK para a
\
operação " ", que, no seu exemplo, basicamente percorre os valores dea
, inverte-os e multiplica-os pelos valores deb
. Para este exemplo, no entanto, você deve usarb./diag(a)
, o que é muito mais rápido.Para sistemas densos, o operador de barra invertida é um pouco mais complicado. Uma breve descrição do que é feito quando é fornecida aqui . De acordo com essa descrição, no seu exemplo, o Matlab resolveria
a\b
usando a substituição reversa. Para matrizes quadradas gerais, é usada uma decomposição LU.fonte
tic; for k=1:100, a\b; end; toc
.Como regra geral, se você tem uma matriz esparsa de complexidade razoável (ou seja, não precisa ser o estêncil de 5 pontos, mas pode de fato ser uma discretização das equações de Stokes para as quais o número de não zeros por linha é muito maior que 5), um solucionador direto esparso, como o UMFPACK, geralmente vence um solucionador iterativo de Krylov se o problema não for maior que cerca de 100.000 incógnitas.
Em outras palavras, para a maioria das matrizes esparsas resultantes de discretizações 2D, um solucionador direto é a alternativa mais rápida. Somente para problemas em 3D nos quais você rapidamente ultrapassa as 100.000 incógnitas, torna-se imperativo usar um solucionador iterativo.
fonte