Berulang kali memecahkan dengan , berbeda

12

Saya menggunakan MATLAB untuk memecahkan masalah yang melibatkan penyelesaian di setiap timestep, di mana berubah seiring waktu. Saat ini, saya menyelesaikan ini menggunakan MATLAB :bAx=bbmldivide

x = A\b

Saya memiliki fleksibilitas untuk membuat sebanyak mungkin perhitungan yang diperlukan, jadi saya bertanya-tanya apakah ada metode yang lebih cepat dan / atau lebih akurat daripada mldivide. Apa yang biasanya dilakukan di sini? Terima kasih semuanya!

Keraguan
sumber
1
Apakah Anda memiliki pengetahuan khusus tentang struktur ? Misalnya, apakah simetris? Yang pasti positif? Tridiagonal? Orthogonal? A
Dominique
Matriks adalah matriks kotak yang padat. A
Keraguan
3
Jika Anda tidak memiliki pengetahuan lain tentang , faktorisasi seperti dijelaskan dalam jawaban di bawah ini adalah taruhan terbaik Anda. L UALU
Dominique

Jawaban:

14

Hal paling jelas yang dapat Anda lakukan adalah melakukan precompute

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

Maka Anda hanya menghitung

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

Ini akan sangat mengurangi biaya dan membuatnya lebih cepat. Akurasi akan sama.

Milind R
sumber
1
Catatan, dari dokumentasi , L tidak selalu segitiga bawah. Jawaban ini kemungkinan akan lebih cepat daripada penyelesaian langsung, namun saya akan berhati-hati untuk memastikan bahwa perintah L \ b cukup pintar untuk diketahui untuk menyelesaikan L dalam urutan yang benar (kemungkinan besar adalah, tetapi tidak dikatakan dengan pasti dalam dokumentasi).
Godric Seer
Ya Anda benar, L adalah produk dari matriks segitiga-lebih rendah dan matriks permutasi. Tetapi saya akan terkutuk jika tidak menyadari bahwa yang harus dilakukan hanyalah penggantian dengan yang terbelakang L\b. Karena saya telah melihat baris yang tepat ini digunakan dalam kode kinerja tinggi oleh mereka yang saya anggap ahli.
Milind R
8
mldivide mengenali matriks segitiga yang diijinkan dan melakukan hal yang benar dalam menyelesaikan sistem seperti itu. Namun, dalam percobaan saya, ini tampaknya membuat proses solusi lebih lambat dengan faktor 10 atau lebih untuk matriks ukuran 2000 oleh 2000 hingga 10.000 oleh 10000. Dengan demikian Anda akan lebih baik melacak permutasi secara eksplisit dengan menggunakan [L , U, P] = lu (P). O(n2)
Brian Borchers
1
Juga, jika matriks Anda jarang, Anda harus mengambil keuntungan dari sparsity dalam menyelesaikan sistem. Cara paling sederhana untuk melakukan ini adalah memastikan bahwa disimpan dalam format jarang dengan menggunakan A = jarang (A) sebelum menghitung faktorisasi LU. Anda juga dapat mencoba mengubah urutan baris A sehingga mengurangi pengisian selama faktorisasi LU. A
Brian Borchers
3
@BrianBorcher Sejauh yang saya tahu, cara terbaik untuk melacak permutasi adalah [L,U,p] = lu(A,'vector'); x = U\(L\b(p));Lihat contoh 3 di lu dokumen .
Stefano M
5

Kami melakukan beberapa laboratorium komputer dalam kursus komputasi ilmiah kami tentang topik ini. Untuk perhitungan "kecil" yang kami lakukan di sana, operator backslash Matlab selalu lebih cepat daripada yang lain, bahkan setelah kami mengoptimalkan kode kami sebanyak mungkin dan menyusun ulang semua matriks sebelumnya (misalnya dengan pemesanan Reverse Cuthill McKee untuk matriks jarang) .

Anda dapat memeriksa salah satu instruksi lab kami . Jawaban untuk pertanyaan Anda dibahas (segera) di halaman 4.

Buku bagus tentang topik ini ditulis misalnya oleh Cheney .

seb
sumber
4

Misalkan adalah matriks padat dan Anda harus menyelesaikan , . Jika adalah cukup besar maka tidak ada yang salah dalamn × n A x i = b i i = 1 ... m mAn×n Axi=bii=1mm

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

Flops adalah untuk dan untuk , oleh karena itu untuk menentukan nilai impas untuk beberapa eksperimen diperlukan ...O ( n 2 ) mO(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

Dalam contoh sepele ini pra-perhitungan lebih baik daripada maju dan mundur solusi untuk . L U m > 125A1LUm>125

Beberapa catatan

Untuk analisis stabilitas dan kesalahan, silakan lihat komentar untuk jawaban yang berbeda ini , terutama yang oleh VictorLiu.

Waktu yang diusulkan sama sekali tidak "ilmiah", tetapi dimaksudkan untuk menunjukkan bahwa pendekatan yang diusulkan dalam jawaban oleh Milind R, sementara itu masuk akal jika diimplementasikan dalam C atau Fortran dengan memanggil subrutin LAPACK dan BLAS yang relevan, mungkin terbukti tidak begitu efektif di Matlab, bahkan untuk .mn

Pengaturan waktu dilakukan dengan Matlab R2011b pada komputer 12 inti dengan rata-rata beban UNIX 5 yang cukup konstan; tic, tocwaktu terbaik dari tiga probe.

Stefano M
sumber
Memang, ada jauh lebih paralelisme yang tersedia dalam multiply matriks-vektor daripada pemecah segitiga, jadi ini harus lebih jelas jika perhitungan dilakukan secara paralel (multicore / GPU / dll ...) dengan cara apa pun.
Aron Ahmadia
@AronAhmadia Saya setuju: estimasi titik impas hanya berdasarkan jumlah operasi masuk akal hanya untuk implementasi serial.
Stefano M
1
Perhatikan bahwa hal-hal akan sangat berbeda jika matriks A jarang - kebalikannya biasanya cukup padat, sedangkan faktor LU biasanya jarang, membalikkan hal-hal kembali ke arah LU menjadi lebih cepat.
Brian Borchers
1
@Ragu akurasi sudah dialamatkan di komentar untuk jawaban ini . Secara umum seharusnya hanya ada kehilangan akurasi yang dapat diabaikan, kecuali Anda memiliki matriks patologis . A
Stefano M
1
@MilindR tentu saja precomputing inv(A)masuk akal hanya jika Anda harus berulang kali menyelesaikan untuk berbeda yang tidak semuanya diketahui pada saat yang sama. Biasanya jika Anda memiliki banyak sisi kanan, kumpulkan saja dalam matriks dan ikuti . b BAx=bbBA\B
Stefano M
2

Lihatlah pertanyaan ini , jawabannya menunjukkan bahwa mldivideitu cukup pintar, dan juga memberikan saran bagaimana cara melihat apa yang Matlab gunakan untuk menyelesaikannya A\b. Ini mungkin memberi Anda petunjuk tentang opsi pengoptimalan.

Psirus
sumber
0

Menggunakan backslash kurang lebih sama dengan inv(A)*B, jika Anda mengkodekannya secara bebas, yang terakhir mungkin lebih intuitif. Mereka hampir sama (hanya berbeda dalam bagaimana perhitungan dilakukan), meskipun Anda harus memeriksa dokumentasi Matlab untuk klarifikasi.

Untuk menjawab pertanyaan Anda, backslash umumnya baik-baik saja, tetapi itu tergantung pada sifat-sifat matriks massa.

AlanH
sumber
1
Secara matematis inv (A) * b sama dengan \ namun secara numerik, sebenarnya membentuk invers keduanya kurang efisien dan kurang akurat. Jika Anda sedang belajar aljabar linier, ini mungkin dapat diterima, tetapi saya berpendapat Anda perlu alasan yang sangat bagus untuk membentuk inversi.
Godric Seer
Tetapi mengapa Anda menghitung inv(A)karena itu saja lebih mahal daripada A\b?
Dominique
7
@Godric: Ada makalah baru-baru ini yang membahas "mitos" yang inv (A) * b kurang akurat: di ArXiv . Tidak mengatakan bahwa biasanya ada alasan untuk menghitung invers yang sebenarnya, tetapi katakan saja.
Victor Liu
3
@Dominique: Solves segitiga jauh lebih tidak dapat diparalelkan daripada perkalian matriks-vektor, dan metode iteratif prakondisi yang canggih sering menggunakan metode langsung pada subdomain. Seringkali berguna untuk secara eksplisit membentuk invers dari beberapa matriks segitiga padat berukuran sedang untuk meningkatkan paralelisme.
Jack Poulson
@ ViktorLiu: Terima kasih atas artikelnya. Saya berdiri dikoreksi pada pernyataan keakuratan saya (minimal untuk implementasi cerdas inv (A)).
Godric Seer