Bagaimana operator backslash MATLAB memecahkan

36

Saya membandingkan beberapa kode saya dengan "stok" kode MATLAB. Saya terkejut dengan hasilnya.

Saya menjalankan kode sampel (Matriks Jarang)

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;

Hasil:

    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.

Untuk Matriks Padat:

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;

Hasil:

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.

Bagaimana sih a \ b begitu mengagumkan?

Pemeriksaan resmi
sumber
1
Backslash bawaan MATLAB, dengan kata lain pemecah langsung untuk sistem persamaan linear, menggunakan metode Multifrontal untuk matriks jarang, itu sebabnya A \ B sangat mengagumkan.
Shuhao Cao
1
Ini menggunakan kode Tim Davis yang tersedia di cise.ufl.edu/research/sparse . Juga kehebatan hilang ketika Anda memiliki masalah non-sepele
stali
1
Apa itu "LULU"? Menurut Anda mengapa ini merupakan implementasi faktorisasi LU yang baik dan penyelesaian langsung berikutnya?
Jed Brown
3
@Nunoxic Implementasi apa ? Apakah Anda menulisnya sendiri? Aljabar linier padat berkinerja tinggi, sementara biasanya secara algoritmik dipahami dengan baik, tidak mudah diimplementasikan secara efisien pada perangkat keras modern. Implementasi BLAS / Lapack terbaik harus mendekati puncak untuk matriks sebesar itu. Juga, dari komentar Anda, saya mendapat kesan bahwa Anda berpikir LU dan Gaussian Elimination adalah algoritma yang berbeda.
Jed Brown
1
Itu memanggil kode Fortran ditulis menggunakan Intel MKL.
Pemeriksaan

Jawaban:

37

Dalam Matlab, perintah '\' memanggil algoritma yang tergantung pada struktur matriks A dan mencakup pemeriksaan (overhead kecil) pada properti A.

  1. Jika A jarang dan berpita, gunakan pemecah berpita.
  2. Jika A adalah matriks segitiga atas atau bawah, gunakan algoritma substitusi mundur.
  3. Jika A simetris dan memiliki elemen diagonal positif nyata, cobalah faktorisasi Cholesky. Jika A jarang, gunakan pemesanan ulang terlebih dahulu untuk meminimalkan pengisian.
  4. Jika tidak ada kriteria di atas yang dipenuhi, lakukan faktorisasi segitiga umum menggunakan eliminasi Gaussian dengan pivoting parsial.
  5. Jika A jarang, maka gunakan perpustakaan UMFPACK.
  6. Jika A tidak kuadrat, gunakan algoritma berdasarkan faktorisasi QR untuk sistem yang tidak ditentukan.

Untuk mengurangi overhead, dimungkinkan untuk menggunakan perintah linsolve di Matlab dan pilih sendiri solver di antara opsi-opsi ini.

Allan P. Engsig-Karup
sumber
Dengan asumsi saya berurusan dengan matriks padat tidak terstruktur 10000x10000 dengan semua elemen bukan nol (tingkat kepadatan tinggi), apa yang akan menjadi taruhan terbaik saya? Saya ingin mengisolasi 1 algoritma yang berfungsi untuk matriks padat. Apakah LU, QR atau Eliminasi Gaussian?
Pemeriksaan
1
Kedengarannya seperti Langkah 4 di mana Gaussian Elimination dipanggil yang sesuai dengan kasus paling umum di mana tidak ada struktur A yang dapat dieksploitasi untuk meningkatkan kinerja. Jadi, pada dasarnya ini adalah faktorisasi LU dan selanjutnya maju diikuti oleh langkah substitusi mundur.
Allan P. Engsig-Karup
Terima kasih! Saya pikir itu memberi saya arahan untuk berpikir. Saat ini, Eliminasi Gaussian adalah yang terbaik yang kami miliki untuk menyelesaikan masalah yang tidak terstruktur seperti itu, apakah itu benar?
Pemeriksaan
37

Jika Anda ingin melihat apa yang a\bdilakukan untuk matriks khusus Anda, Anda dapat mengatur spparms('spumoni',1)dan mencari algoritma apa yang membuat Anda terkesan. Sebagai contoh:

spparms('spumoni',1);
A = delsq(numgrid('B',256));
b = rand(size(A,2),1);
mldivide(A,b);  % another way to write A\b

akan menampilkan

sp\: bandwidth = 254+1+254.
sp\: is A diagonal? no.
sp\: is band density (0.01) > bandden (0.50) to try banded solver? no.
sp\: is A triangular? no.
sp\: is A morally triangular? no.
sp\: is A a candidate for Cholesky (symmetric, real positive diagonal)? yes.
sp\: is CHOLMOD's symbolic Cholesky factorization (with automatic reordering) successful? yes.
sp\: is CHOLMOD's numeric Cholesky factorization successful? yes.
sp\: is CHOLMOD's triangular solve successful? yes.

jadi saya bisa melihat bahwa "\" akhirnya menggunakan "CHOLMOD" dalam kasus ini.

dranxo
sumber
3
+1 untuk pengaturan MATLAB baru yang belum pernah saya dengar. Bermain bagus, tuan.
Geoff Oxberry
2
Hai, terima kasih! Ini di help mldivide.
dranxo
16

Untuk matriks jarang, Matlab menggunakan UMFPACK untuk \operasi " ", yang, dalam contoh Anda, pada dasarnya dijalankan melalui nilai - nilai a, membalikkannya, dan mengalikannya dengan nilai - nilai dari b. Namun, untuk contoh ini, Anda harus menggunakan b./diag(a), yang jauh lebih cepat.

Untuk sistem yang padat, operator backslash sedikit lebih rumit. Deskripsi singkat tentang apa yang dilakukan saat diberikan di sini . Menurut deskripsi itu, dalam contoh Anda, Matlab akan menyelesaikan a\bmenggunakan substitusi mundur. Untuk matriks kuadrat umum, dekomposisi LU digunakan.

Pedro
sumber
Regd. Sparsity, inv dari sebuah matriks diag hanya akan menjadi kebalikan dari elemen diagonal sehingga b./diag(a) akan bekerja tetapi a \ b bekerja dengan sangat baik untuk matriks umum yang jarang juga. Mengapa tidak linsolve atau LULU (versi LU saya yang dioptimalkan) tidak lebih cepat dari \ b untuk matriks padat dalam kasus itu.
Pemeriksaan
@Nunoxic Apakah LULU Anda melakukan sesuatu untuk mendeteksi diagonalitas atau triangularity dari matriks padat? Jika tidak, ini akan memakan waktu sama lama dengan setiap matriks, terlepas dari isi atau strukturnya.
Pedro
Agak. Tapi, dengan flag OPT linsolve, saya mendefinisikan semua yang ada untuk mendefinisikan tentang struktur. Namun, a \ b lebih cepat.
Pemeriksaan
@Nooxic, setiap kali Anda memanggil fungsi pengguna, Anda menyebabkan biaya overhead. Matlab melakukan segalanya untuk backslash secara internal, misalnya dekomposisi dan penerapan selanjutnya dari sisi kanan, dengan overhead yang sangat sedikit, dan dengan demikian akan lebih cepat. Selain itu, dalam pengujian Anda, Anda harus menggunakan lebih dari satu panggilan untuk mendapatkan pengaturan waktu yang andal, misalnya tic; for k=1:100, a\b; end; toc.
Pedro
5

Sebagai aturan praktis, jika Anda memiliki matriks tipis kompleksitas yang masuk akal (yaitu, itu tidak harus menjadi stensil 5 poin tetapi sebenarnya bisa menjadi diskritisasi dari persamaan Stokes yang jumlah nonzeros per baris adalah jauh lebih besar dari 5), maka pemecah langsung yang jarang seperti UMFPACK biasanya mengalahkan pemecah Krylov yang berulang jika masalahnya tidak lebih besar dari sekitar mungkin 100.000 yang tidak diketahui.

Dengan kata lain, untuk sebagian besar matriks jarang yang dihasilkan dari diskresi 2d, pemecah langsung adalah alternatif tercepat. Hanya untuk masalah 3d di mana Anda dengan cepat mendapatkan di atas 100.000 yang tidak diketahui apakah penting untuk menggunakan pemecah berulang.

Wolfgang Bangerth
sumber
3
Tidak jelas bagi saya bagaimana ini menjawab pertanyaan, tetapi saya juga mengambil masalah dengan premis. Memang benar bahwa pemecah langsung cenderung bekerja dengan baik untuk masalah ukuran 2D yang sederhana, tetapi pemecah langsung cenderung menderita dalam 3D jauh sebelum 100k tidak diketahui (pemisah titik jauh lebih besar daripada dalam 2D). Lebih jauh, saya mengklaim bahwa dalam kebanyakan kasus (mis. Operator eliptik), solver iteratif dapat dibuat lebih cepat daripada solver langsung bahkan untuk masalah 2D berukuran sedang, tetapi mungkin perlu upaya yang signifikan untuk melakukannya (misalnya menggunakan bahan yang tepat untuk membuat kinerja multigrid) .
Jed Brown
1
Jika masalah Anda cukup kecil dan Anda tidak ingin berpikir tentang merancang pemecah implisit, atau jika masalah Anda sangat sulit (seperti Maxwell frekuensi tinggi) dan Anda tidak ingin mengabdikan karir Anda untuk merancang pemecah yang baik, maka saya setuju bahwa pemecah langsung yang jarang adalah pilihan yang bagus.
Jed Brown
Sebenarnya masalah saya adalah merancang pemecah padat yang baik. Saya tidak memiliki aplikasi khusus seperti itu (Oleh karena itu, tidak ada struktur). Saya ingin mengubah beberapa kode saya dan membuatnya kompetitif dengan apa yang saat ini digunakan. Saya hanya ingin tahu tentang a dan bagaimana itu selalu mengalahkan kode saya.
Pemeriksaan
@JedBrown: Ya, mungkin dengan upaya yang signifikan orang bisa mendapatkan solver berulang untuk mengalahkan solver langsung bahkan untuk masalah 2d kecil. Tetapi mengapa melakukannya? Untuk masalah dengan <100k yang tidak diketahui, solver langsung jarang dalam 2d cukup cepat. Yang ingin saya katakan adalah: untuk masalah kecil seperti itu, jangan habiskan waktu Anda bermain-main dan mencari tahu kombinasi parameter terbaik - cukup ambil kotak hitam.
Wolfgang Bangerth
Sudah ada perbedaan urutan run-time besarnya antara Cholesky jarang dan multigrid geometrik (berbasis matriks) untuk masalah 2D "mudah" dengan 100k dofs menggunakan stensil 5-titik (~ 0,5 detik dibandingkan dengan ~ 0,05 detik). Jika stensil Anda menggunakan tetangga kedua (mis. Diskritisasi urutan keempat, Newton untuk beberapa pilihan reologi nonlinier, stabilisasi, dll.), Ukuran pemisah simpul kira-kira dua kali lipat, sehingga biaya penyelesaian langsung naik sekitar 8x (biaya lebih tergantung masalah untuk MG). Dengan banyak langkah waktu atau putaran optimisasi / UQ, perbedaan ini sangat signifikan.
Jed Brown