试图在matlab中提高三重for循环的效率

时间:2014-06-06 22:19:06

标签: performance matlab for-loop vectorization

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

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

非常感谢你的帮助。

2 个答案:

答案 0 :(得分:2)

矢量化的替代方法是识别代码中昂贵的操作并以某种方式减少它们。例如,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秒。

答案 1 :(得分:0)

这是使用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 秒...