Il fast è ciò di cui dovresti preoccuparti, non necessariamente la completa vettorizzazione. Le versioni recenti di Matlab sono molto più intelligenti su come gestire i loop in modo efficiente. Se c'è un modo vettoriale compatto di esprimere qualcosa, di solito è più veloce, ma i loop non dovrebbero (sempre) essere temuti come un tempo.
clc
A = rand(5000)>0.5;
A(1,find(sum(A,1)==0)) = 1; % make sure there is at least one match
% Slow because it is doing too much work
tic;[B,I1]=max(cumsum(A));toc
% Fast because FIND is fast and it runs the inner loop
tic;
I3=zeros(1,5000);
for i=1:5000
I3(i) = find(A(:,i),1,'last');
end
toc;
assert(all(I1==I3));
% Even faster because the JIT in Matlab is smart enough now
tic;
I2=zeros(1,5000);
for i=1:5000
I2(i) = 0;
for j=5000:-1:1
if A(j,i)
I2(i) = j;
break;
end
end
end
toc;
assert(all(I1==I2));
Su R2008a, Windows, x64, la versione cumSum richiede 0,9 secondi. Il ciclo e la versione di ricerca impiegano 0,02 secondi. La versione a doppio loop richiede solo 0,001 secondi.
EDIT: Qual è il più veloce dipende dai dati effettivi. Il doppio ciclo richiede 0,05 secondi quando si cambia da 0,5 a 0,999 (perché in media ci vuole più tempo per battere la pausa). cumsum e il loop & trovano un'implementazione con più velocità coerenti.
EDIT 2: soluzione flipud di gnovice è intelligente. Sfortunatamente, sulla mia macchina di prova ci vogliono 0,1 secondi, quindi è molto più veloce di cumsum, ma più lento delle versioni ad anello.
fonte
2009-05-06 21:52:53
Idea intelligente. Sfortunatamente, è circa 5 volte più lento del ciclo e trova. –
Questo è un po 'il risultato che mi aspettavo: più veloce di CUMSUM ma ancora più lento del looping ... anche se dipende tutto dalla dimensione e dalla frazione di riempimento di A (che l'OP non ha realmente definito). – gnovice