2013-08-17 103 views
0

我正在處理一個帶有三個嵌套for循環的函數,對於其預期用途來說太慢了。瓶頸顯然是循環部分 - 幾乎100%的執行時間都花在最內層的循環中。
該函數採用名爲rM作爲輸入二維矩陣,並返回一個名爲ec 3D矩陣:Matlab - 加速嵌套For循環

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 

關於加快for循環任何幫助,將不勝感激......

+1

它看起來像第二環路可以被矢量:除去'當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感謝您的suggestions..I'm也非常驚奇,爲什麼向量化版本比循環更慢(請參閱我的問題中的更新)。 – 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