Saya bekerja dengan Matlab.
Saya memiliki matriks persegi biner. Untuk setiap baris, ada satu atau lebih entri dari 1. Saya ingin menelusuri setiap baris dari matriks ini dan mengembalikan indeks 1s tersebut dan menyimpannya di entri sel.
Saya bertanya-tanya apakah ada cara untuk melakukan ini tanpa mengulang semua baris matriks ini, karena untuk loop sangat lambat di Matlab.
Sebagai contoh, matriks saya
M = 0 1 0
1 0 1
1 1 1
Kemudian akhirnya, saya ingin sesuatu seperti
A = [2]
[1,3]
[1,2,3]
Begitu A
juga sel.
Apakah ada cara untuk mencapai tujuan ini tanpa menggunakan for loop, dengan tujuan menghitung hasilnya lebih cepat?
matlab
vectorization
ftxx
sumber
sumber
for
loop? Untuk masalah ini, dengan versi modern MATLAB, saya sangat curiga satufor
loop menjadi solusi tercepat. Jika Anda memiliki masalah kinerja, saya curiga Anda mencari di tempat yang salah untuk solusi berdasarkan saran usang.cellfun
.1
dalam satu baris yang khas? Saya tidak akan mengharapkanfind
loop untuk mengambil sesuatu yang mendekati 30-an untuk sesuatu yang cukup kecil agar sesuai dengan memori fisik.Jawaban:
Di bagian bawah jawaban ini adalah beberapa kode pembandingan, karena Anda mengklarifikasi bahwa Anda tertarik pada kinerja daripada secara acak menghindari
for
loop.Bahkan, saya pikir
for
loop mungkin merupakan opsi yang paling performant di sini. Karena mesin JIT "baru" (2015b) diperkenalkan ( sumber ),for
loop pada dasarnya tidak lambat - bahkan mereka dioptimalkan secara internal.Anda dapat melihat dari patokan bahwa
mat2cell
opsi yang ditawarkan oleh ThomasIsCoding di sini sangat lambat ...Jika kita menyingkirkan garis itu untuk membuat skala lebih jelas, maka
splitapply
metode saya cukup lambat, opsi akumulator obchardon sedikit lebih baik, tetapi opsi tercepat (dan sebanding) baik menggunakanarrayfun
(seperti juga disarankan oleh Thomas) ataufor
loop. Perhatikan bahwaarrayfun
pada dasarnya ini adalahfor
lingkaran yang menyamar untuk sebagian besar kasus penggunaan, jadi ini bukan ikatan yang mengejutkan!Saya akan merekomendasikan Anda menggunakanfor
loop untuk meningkatkan keterbacaan kode dan kinerja terbaik.Edit :
Jika kita menganggap bahwa perulangan adalah pendekatan tercepat, kita dapat membuat beberapa optimisasi di sekitar
find
perintah.Secara khusus
Buat
M
logis. Seperti yang ditunjukkan plot di bawah ini, ini bisa lebih cepat untuk yang relatif kecilM
, tetapi lebih lambat dengan trade-off konversi tipe untuk yang besarM
.Gunakan logis
M
untuk mengindeks array1:size(M,2)
daripada menggunakanfind
. Ini menghindari bagian paling lambat dari loop (find
perintah) dan melebihi jenis overhead konversi, menjadikannya pilihan tercepat.Inilah rekomendasi saya untuk kinerja terbaik:
Saya telah menambahkan ini ke patokan di bawah, di sini adalah perbandingan pendekatan loop-style:
Kode pembandingan:
sumber
M
. Misalnya, jika hanya 5% elemen yang terisiM = randi([0,20],N) == 20;
makafor
loop adalah yang paling lambat danarrayfun
metode Anda menang.accumarray
tanpaind2sub
, tetapi lebih lambat darifor
loopAnda dapat mencoba
arrayfun
seperti di bawah ini, yang menyapu barisM
atau (pendekatan yang lebih lambat oleh
mat2cell
)sumber
arrayfun
pada dasarnya adalah loop-in-disguise, jadi ini mungkin gagal di kedua front 1) menghindari loop dan 2) menjadi cepat, seperti yang diharapkan oleh OPSunting : Saya menambahkan patokan, hasilnya menunjukkan itu perulangan for lebih efisien daripada
accumarray
.Anda dapat menggunakan
find
danaccumarray
:Matriks dipindahkan (
A'
) karenafind
dikelompokkan berdasarkan kolom.Contoh:
Keluaran:
Benchmark:
Hasil:
A for loop lebih efisien daripada
accumarray
...sumber
Menggunakan diakarray :
sumber
MM{I} = find(M(I, :))
.ind2sub
:[ii, jj] = find(M); accumarray(ii, jj, [], @(x){x})
Anda dapat menggunakan strfind :
sumber
string
tipe yang sebenarnya , daripada karakter? Ada banyak optimisasi untuk string, karenanya mengapa mereka ada ...