Nhanh chóng là những gì bạn nên lo lắng, không nhất thiết phải vector hóa đầy đủ. Các phiên bản gần đây của Matlab là nhiều hơn thông minh hơn về việc xử lý vòng lặp hiệu quả. Nếu có một cách vectorized nhỏ gọn để thể hiện một cái gì đó, nó thường là nhanh hơn, nhưng vòng lặp không nên (luôn luôn) được lo sợ như họ từng là.
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));
Trên R2008a, Windows, x64, phiên bản cumsum mất 0,9 giây. Vòng lặp và tìm phiên bản mất 0,02 giây. Phiên bản vòng lặp đôi chỉ mất 0,001 giây.
EDIT: Cách nào nhanh nhất phụ thuộc vào dữ liệu thực tế. Vòng lặp kép mất 0,05 giây khi bạn thay đổi 0,5 đến 0,999 (vì phải mất nhiều thời gian hơn để đạt đến điểm ngắt; trung bình). cumsum và vòng lặp & tìm việc triển khai có tốc độ phù hợp hơn.
CHỈNH SỬA 2: Giải pháp lật ngược của gnovice rất thông minh. Thật không may, trên máy thử nghiệm của tôi phải mất 0,1 giây, do đó, nó nhanh hơn nhiều so với cumsum, nhưng chậm hơn so với các phiên bản looped.
Nguồn
2009-05-06 21:52:53
Ý tưởng thông minh. Thật không may, đó là khoảng 5x chậm hơn so với vòng lặp và tìm thấy. –
Đó là kinda kết quả tôi mong đợi: nhanh hơn CUMSUM nhưng vẫn chậm hơn looping ... mặc dù tất cả vẫn còn phụ thuộc vào kích thước và điền phần A (mà OP đã không thực sự xác định). – gnovice