减少MATLAB中嵌套for循环的执行时间

时间:2016-08-09 11:40:26

标签: performance matlab vectorization

我正在为一篇论文写一篇目标函数。它需要一个嵌套循环,如下所示:

for j=1:m   
    if j==m        
        for i=1:n           
            consumedE(j) = consumedE(j)+ b(i,j)*e(i,j);
            for k=1:m-1
                for l=1:n                   
                    consumedE(j) = consumedE(j) + b(i,j)*(et(end)*Data(i).Vin);                    
                end                
            end          
        end
    else
        for i=1:n
            consumedE(j) = consumedE(j) + b(i,j)*(e(i,j)+et(j)*Data(i).Vout);
        end
    end
end

其中m和n约为200。

即使在非常强大的PC上,它也非常耗时。我怎样才能加快速度?

2 个答案:

答案 0 :(得分:0)

在你的内心循环中,你根本不参考你的内在指数。

        for k=1:m-1
            for l=1:n                   
                consumedE(j) = consumedE(j) + b(i,j)*(et(end)*Data(i).Vin);                    
            end                
        end 

这应该与:

相同
consumedE(j) = consumedE(j)+ (m-1)*n*b(i,j)*(et(end)*Data(i).Vin);

我希望这会显着提升效果。

答案 1 :(得分:0)

让我们创建一些随机样本数据。我将Data(i).Vout简化为向量DataVout。您可以使用[Data.Vout].'轻松完成此操作。 Data.Vin也是如此。

m = 10;
n = 5;
b = rand(n,m);
e = rand(n,m);
et = rand(1,m);
DataVout = rand(n,1);
DataVin = rand(n,1);

现在,您的else子句是遍历所有ij的循环,您可以在其中为每个组合执行以下操作:

b(i,j) * ( e(i,j) + et(j) * Data(i).Vout )

然后你总结所有i。您可以通过以下步骤以矢量化方式执行此操作:

  1. 矩阵乘法DataVout * et创建一个包含et(j) * DataVout(i)的矩阵。此矩阵的大小为 n-by-m ,其大小与eb相同。
  2. e添加到此矩阵,并在结果与b之间进行逐元素相乘。这是:b .* (e + DataVout * et)
  3. 汇总所有行:consumedE = sum(b .* (e + DataVout * et), 1)
  4. 最后一个值j==m在您的计算中很特别:您重复内部计算n * (m-1)次,因为您不使用kl任何计算。这导致

    b(i,j) * ( e(i,j) + n * (m-1) * et(j) * Data(i).Vin )
    

    与之前的计算相同 - 除了Data.Vout替换为n*(m-1)*Data.Vin(你确定这是正确的吗?) 我们可以简化先前的计算,因为我们只对单个固定j=m进行计算,这导致了 sum(b(:,m) .* (e(:,m) + n * (m-1) * DataVin * et(m)), 1)

    一切都在一起,整个代码变成:

    consumedE = sum(b .* (e + DataVout * et), 1);
    consumedE(m) = sum(b(:,m) .* (e(:,m) + n * (m-1) * DataVin * et(m)), 1);
    

    比较:对于m=200n=150,您的代码在我的计算机上占用0.109523 seconds。向量化代码采用0.005665 seconds,这是因子20的加速。