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 menggunakan arrayfun
(seperti juga disarankan oleh Thomas) atau for
loop. Perhatikan bahwa arrayfun
pada dasarnya ini adalah for
lingkaran yang menyamar untuk sebagian besar kasus penggunaan, jadi ini bukan ikatan yang mengejutkan!
Saya akan merekomendasikan Anda menggunakan for
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 kecil M
, tetapi lebih lambat dengan trade-off konversi tipe untuk yang besar M
.
Gunakan logis M
untuk mengindeks array 1:size(M,2)
daripada menggunakan find
. Ini menghindari bagian paling lambat dari loop ( find
perintah) dan melebihi jenis overhead konversi, menjadikannya pilihan tercepat.
Inilah rekomendasi saya untuk kinerja terbaik:
function A = f_forlooplogicalindexing( M )
M = logical(M);
k = 1:size(M,2);
N = size(M,1);
A = cell(N,1);
for r = 1:N
A{r} = k(M(r,:));
end
end
Saya telah menambahkan ini ke patokan di bawah, di sini adalah perbandingan pendekatan loop-style:
Kode pembandingan:
rng(904); % Gives OP example for randi([0,1],3)
p = 2:12;
T = NaN( numel(p), 7 );
for ii = p
N = 2^ii;
M = randi([0,1],N);
fprintf( 'N = 2^%.0f = %.0f\n', log2(N), N );
f1 = @()f_arrayfun( M );
f2 = @()f_mat2cell( M );
f3 = @()f_accumarray( M );
f4 = @()f_splitapply( M );
f5 = @()f_forloop( M );
f6 = @()f_forlooplogical( M );
f7 = @()f_forlooplogicalindexing( M );
T(ii, 1) = timeit( f1 );
T(ii, 2) = timeit( f2 );
T(ii, 3) = timeit( f3 );
T(ii, 4) = timeit( f4 );
T(ii, 5) = timeit( f5 );
T(ii, 6) = timeit( f6 );
T(ii, 7) = timeit( f7 );
end
plot( (2.^p).', T(2:end,:) );
legend( {'arrayfun','mat2cell','accumarray','splitapply','for loop',...
'for loop logical', 'for loop logical + indexing'} );
grid on;
xlabel( 'N, where M = random N*N matrix of 1 or 0' );
ylabel( 'Execution time (s)' );
disp( 'Done' );
function A = f_arrayfun( M )
A = arrayfun(@(r) find(M(r,:)),1:size(M,1),'UniformOutput',false);
end
function A = f_mat2cell( M )
[i,j] = find(M.');
A = mat2cell(i,arrayfun(@(r) sum(j==r),min(j):max(j)));
end
function A = f_accumarray( M )
[val,ind] = ind2sub(size(M),find(M.'));
A = accumarray(ind,val,[],@(x) {x});
end
function A = f_splitapply( M )
[r,c] = find(M);
A = splitapply( @(x) {x}, c, r );
end
function A = f_forloop( M )
N = size(M,1);
A = cell(N,1);
for r = 1:N
A{r} = find(M(r,:));
end
end
function A = f_forlooplogical( M )
M = logical(M);
N = size(M,1);
A = cell(N,1);
for r = 1:N
A{r} = find(M(r,:));
end
end
function A = f_forlooplogicalindexing( M )
M = logical(M);
k = 1:size(M,2);
N = size(M,1);
A = cell(N,1);
for r = 1:N
A{r} = k(M(r,:));
end
end
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.