【问题标题】:trying to improve the efficency of a triple for loop in matlab试图提高matlab中三重for循环的效率
【发布时间】:2014-06-06 22:19:06
【问题描述】:

我正在尝试矢量化或使这个循环运行得更快(这是一个最少的代码):

n=1000;
L=100;
x=linspace(-L/2,L/2);
V1=rand(n);
for i=1:length(x)
    for k=1:n
        for j=1:n
            V2(j,k)=V1(j,k)*log(2/L)*tan(pi/L*(x(i)+L/2)*j);
        end
    end
    V3(i,:)=sum(V2);
end

非常感谢您的帮助。

【问题讨论】:

    标签: performance matlab for-loop vectorization


    【解决方案1】:

    向量化的替代方法是识别代码中昂贵的操作并以某种方式减少它们。例如,log(2/L) 被调用 100*1000*1000 次,输入不依赖于三个 for 循环中的任何一个。如果我们在 for 循环之外计算这个值,那么我们可以使用它来代替:

    logResult = log(2/L);
    

    V2(j,k)=V1(j,k)*log(2/L)*tan(pi/L*(x(i)+L/2)*j);
    

    变成

    V2(j,k)=(V1(j,k)*logResult*tan(pi/L*(x(i)+L/2)*j));
    

    同样,代码调用tan 函数同样100*1000*1000 次。注意这个计算,tan(pi/L*(x(i)+L/2)*j) 不依赖于k。因此,如果我们在 for 循环之外计算这些值,我们可以将这个计算减少 1000 倍:

    tanValues = zeros(lenx,n);
    for i=1:lenx
        for j=1:n
            tanValues(i,j) = tan(pi/L*(x(i)+L/2)*j);
        end
    end
    

    V2(j,k) 的计算变为

    V2(j,k)=V1(j,k)*logResult*tanValues(i,j);
    

    此外,内存可以预先分配给V2V3 矩阵,以避免在每次迭代时发生内部调整大小。只需在for 循环之外执行以下操作

    V2 = zeros(n,n);
    V3 = zeros(lenx,n);
    

    使用 tictoc 在我的工作站上将原始执行时间从 ~14 秒缩短到 ~6 秒。这仍然比 natan 的解决方案(对我来说大约 2 秒)三倍。

    【讨论】:

      【解决方案2】:

      这是使用meshgridbsxfunrepmat 的矢量化解决方案:

      % fast preallocation
      jj(n,n)=0; B(n,n,L)=0; V3(L,n)=0;
      lg=log(2/L);
      
      % the vectorizaion part
      jj=meshgrid(1:n);
      B=bsxfun(@times,ones(n),permute(x,[3 1 2]));
      V3=squeeze(sum(lg*repmat(V1,1,1,numel(x)).*tan(bsxfun(@times,jj',pi/L*(B+L/2))),1)).';
      

      使用 tic\toc 在我的计算机上运行您的代码大约需要 25 秒。 bsxfun 代码耗时 ~4.5 秒...

      【讨论】:

        猜你喜欢
        • 2019-11-06
        • 1970-01-01
        • 1970-01-01
        • 2019-03-07
        • 2015-10-08
        • 1970-01-01
        • 1970-01-01
        • 2018-04-18
        • 1970-01-01
        相关资源
        最近更新 更多