2013-08-17 1 views
0

의도 된 용도로 사용하기에는 너무 느린 3 중첩 for 루프가있는 함수를 작성하고 있습니다. 병목 현상은 분명히 루핑 부분입니다. 실행 시간의 거의 100 %가 가장 안쪽 루프에서 소비됩니다.
기능은 ec라는 차원 매트릭스를 입력으로 rM라는 2 차원 매트릭스를 받아 반환Matlab - 중첩 된 For-Loop 가속화

루프에 대한 속도를 향상에 어떤 도움을 주시면 감사하겠습니다

rows = size(rM, 1); 
cols = size(rM, 2); 

%preallocate. 
ec = zeros(rows+1, cols, numRiskLevels); 
ec(1, :, :) = 100; 

for risk = minRisk:stepRisk:maxRisk; 
    for c = 1:cols, 
     for r = 2:rows+1, 
      ec(r, c, risk) = ec(r-1, c, risk) * (1 + risk * rM(r-1, c)); 
     end 
    end 
end 
... 문제는,이다

+1

두 번째 루프가 벡터화 될 수있는 것처럼 보입니다.'for c = 1 : cols'와 그'end'를 제거하고, 가장 안쪽 라인에서'c'를':'로 바꿉니다. 그건 시간을 줄이는 데 도움이됩니다 –

+0

@ LuisMendo 당신의 제안에 감사드립니다. 구현했지만 흥미롭게도 코드가 이전보다 느리게 실행되었습니다. – bluebox

+0

정확히 무엇을하려고합니까? 아마도 현재의 속도를 높이려는 것보다 다른 계산을 사용하는 것이 가능한 해결책입니까? –

답변

1

내부 루프는 가장 느린 반면, 벡터화하는 것이 거의 불가능합니다. 모든 반복은 이전의 반복에 따라 달라집니다.

바깥이 가능하다 :

clc; 
rM = rand(50); 

rows = size(rM, 1); 
cols = size(rM, 2); 

minRisk = 1; 
stepRisk = 1; 
maxRisk = 100; 
numRiskLevels = maxRisk/stepRisk; 

%preallocate. 
ec = zeros(rows+1, cols, numRiskLevels); 
ec(1, :, :) = 100; 

riskArray = (minRisk:stepRisk:maxRisk)'; 
tic 
for r = 2:rows+1 
    tmp = riskArray * rM(r-1, :); 
    tmp = permute(tmp, [3 2 1]); 
    ec(r, :, :) = ec(r-1, :, :) .* (1 + tmp); 
end 
toc 


%preallocate. 
ec2 = zeros(rows+1, cols, numRiskLevels); 
ec2(1, :, :) = 100; 
tic 
for risk = minRisk:stepRisk:maxRisk; 
    for c = 1:cols 
     for r = 2:rows+1 
      ec2(r, c, risk) = ec2(r-1, c, risk) * (1 + risk * rM(r-1, c)); 
     end 
    end 
end 
toc 

all(all(all(ec == ec2))) 

그러나 놀랍게도

은 벡터화 코드가 실제로 느립니다. (하지만 누군가 코드를 개선 할 수 있기 때문에 내가 그 코드를 남겨 두었다고 생각했습니다.)

+0

+1 제안 해 주셔서 감사합니다. 또한 매우 놀랍습니다. 왜 벡터화 된 버전은 루프보다 느립니다 (내 질문에 업데이 트를 참조하십시오). – bluebox

1

방금 ​​외부 루프를 벡터화하려고 시도했지만 실제로는 속도가 현저히 빨라졌습니다. 물론 (크기)를 모르고 입력을 스크립트의 속도를 판단하기 어렵다 그러나 나는 이것이 좋은 출발점이 될 것입니다 말할 것입니다 :

% Here you can change the input parameters 
riskVec = 1:3:120; 
rM = rand(50); 


%preallocate and calculate non vectorized solution 
ec2 = zeros(size(rM,2)+1, size(rM,1), max(riskVec)); 
ec2(1, :, :) = 100; 
tic 
for risk = riskVec 
    for c = 1:size(rM,2) 
     for r = 2:size(rM,1)+1 
      ec2(r, c, risk) = ec2(r-1, c, risk) * (1 + risk * rM(r-1, c)); 
     end 
    end 
end 
t1=toc; 

%preallocate and calculate vectorized solution 
ec = zeros(size(rM,2)+1, size(rM,1), max(riskVec)); 
ec(1, :, :) = 100; 
tic 
for c = 1:size(rM,2) 
    for r = 2:size(rM,1)+1 
     ec(r, c, riskVec) = ec(r-1, c, riskVec) .* reshape(1 + riskVec * rM(r-1, c),[1 1 length(riskVec)]); 
    end 
end 
t2=toc; 

% Check whether the vectorization is done correctly and show the timing results 
if ec(:) == ec2(:) 
    t1 
    t2 
end 

주어진 출력은 다음과 같습니다

t1 = 

    0.1288 


t2 = 

    0.0408 

따라서 riskVecrM의 경우 벡터화되지 않은 솔루션보다 약 3 배 빠릅니다.

+0

+1 데니스에게 감사드립니다. 나중에 솔루션을 시험해보고 실제 입력 데이터가 얼마나 빠르는지 확인해 보겠습니다. – bluebox