2009-05-06 7 views
9

가정하자 빠르고 벡터화 방식으로 마지막 제로가 아닌 인덱스의 벡터로 진 매트릭스를 켜기 전 요소가 0 또는 1는 MATLAB에서,

은 어떻게받을 수 있나요 매트릭스,을 가지고 더 빠른 벡터화 된 방식으로 각 열의 마지막 0이 아닌 요소의 인덱스 벡터?

나는

[B, I] = max(cumsum(A));

할 및 I를 사용하지만, 더 빠른 방법이 있을까? (저는 cumsum이 0과 1을 합산하는 데 약간의 시간이 걸릴 것이라고 가정합니다).

편집 : 내가 생각하는 나는 내가 빨리 필요한 것보다 더 많은 벡터화 - 씨 Fooz '루프가 훌륭하지만, MATLAB의 각 루프가 빠른 경우에도 디버깅 시간을 나에게 에게 많은 비용을 것입니다.

답변

7

Mr Fooz으로 표시된 것처럼 for 루프는 최신 버전의 MATLAB에서 매우 빠릅니다. 당신이 정말로 컴팩트 벡터화 된 코드를 갖고 싶어하지만, 나는이 시도 제안 : 꽤 빨리 씨 Fooz의 루프 옵션으로 여전히

[B,I] = max(flipud(A)); 
I = size(A,1)-I+1; 

이것은 당신의 CUMSUM 기반 대답보다는 빠르지 만합니다.

두 개의 추가 고려할 사항 :

  • 어떤 결과가 당신이 그것에 전혀 사람이없는 열 얻을 하시겠습니까? 위 옵션을 사용하면 크기 (A, 1) (즉 행 수는)이됩니다. 귀하의 옵션의 경우, I 씨 Fooz에서 중첩를 위해 루프 옵션은 당신이 다른 옵션 0

  • 상대 속도를 제공하면서 가능성에 따라 달라집니다, 당신은 이러한 경우에 1을 얻을 것으로 예상 크기가이고 예상되는 0이 아닌 숫자입니다.

+0

영리한 아이디어. 불행히도, 루프 & 찾기보다 약 5 배 느립니다. –

+0

그것은 다소 기대했던 결과입니다. CUMSUM보다 빠르지 만 루핑보다 느립니다 ... A의 크기와 채우기 비율 (OP가 실제로 정의하지 않은)에 따라 달라 지지만 여전히 느립니다. – gnovice

10

패스트 (Fast)는 반드시 전체 벡터화가 아니라 걱정해야합니다. Matlab의 최신 버전은 입니다. 루프를 효율적으로 처리하는 데 훨씬 더 똑똑한입니다. 컴팩트하게 벡터화 된 방식으로 표현하면, 일반적으로 더 빠르지 만, 예전처럼 루프가 (항상) 두려워해서는 안됩니다.

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)); 

R2008a, Windows, x64에서 누적 버전은 0.9 초 걸립니다. 루프 및 찾기 버전은 0.02 초 걸립니다. 더블 루프 버전은 0.001 초 밖에 걸리지 않습니다.

편집 : 가장 빠른 것은 실제 데이터에 따라 다릅니다. 이중 루프는 0.5에서 0.999로 변경하면 0.05 초가 걸립니다 (평균 시간은 휴식 시간에 걸리기 때문에). cumsum 및 루프 & 찾기 구현은보다 일관된 속도를 가지고 있습니다.

편집 2 : gnovice의 플립 솔루션은 영리합니다. 불행히도, 내 테스트 컴퓨터에서 0.1 초 걸립니다, 그래서 그것은 cumsum보다 훨씬 빠르지 만 반복 버전보다 느립니다.

+0

와우, 빠른 속도로 만들 수있는 루프의 특성입니까? 아니면 이와 유사한 루프가 유사한 작업을 수행하는 가장 빠른 방법일까요? –

+1

예제를 작성하기 시작했을 때 이중 루프가 가장 느리고 루프가 가장 빠를 것으로 예상했습니다. 내부 루프가 완료까지 실행되어야 할 때 다소 느립니다 (2 번 편집 참조). 요즘 Matlab은 모든 기능에 대한 적시 컴파일을 수행합니다. 이렇게하면 루프가 훨씬 빨라집니다 (그러나 EVAL을 사용하려는 사람들에게는 예상치 못한 결과가 있습니다). 일반적으로 벡터화는 추가 작업을 수행하지 않고도 수행 할 수있는 경우 더 유용합니다 (플립 및 cumsum 솔루션은 벡터화되었지만 추가 작업이 필요함). –

+0

주목해야 할 또 다른 흥미로운 점은 대부분의 경우 Matlab의 최신 버전이 표현 구문 분석에 현명하다는 것입니다. E = A. * B. * C. * D; C로 작업을 수동으로 작성하는 경우와 비슷한 방식으로 요소별로 추가 임시 요소없이 실행됩니다. 멀티 코어 지원이 활성화 된 상태에서 Matlab은 작업의 분리 된 부분을 찾아서 다른 작업 영역으로 파생시킵니다 CPU 코어. 호출간에 독립적 인 루프 반복을 나눌만큼 똑똑한 지 모르겠습니다. 테스트를 위해 Core 2 Duo proc를 사용했습니다. –