Matlab - 加速嵌套For-Loops

时间:2013-08-17 10:17:40

标签: performance matlab for-loop

我正在使用三个嵌套for循环的函数,这对于它的预期用途来说太慢了。瓶颈显然是循环部分 - 几乎100%的执行时间都花在了最里面的循环中 该函数采用名为rM的2d矩阵作为输入,并返回一个名为ec的3d矩阵:

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循环的帮助都会受到赞赏......

2 个答案:

答案 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)))

但令我惊讶的是,矢量化代码确实较慢。 (但也许有人可以改进代码,所以我想我把它留给你了。)

答案 1 :(得分: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倍。