我正在尝试向量化或使这个循环运行得更快(这是一个最小的代码):
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
非常感谢你的帮助。
答案 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);
此外,可以将内存预先分配给V2
和V3
矩阵,以避免每次迭代时发生的内部大小调整。只需在for
循环
V2 = zeros(n,n);
V3 = zeros(lenx,n);
使用tic
和toc
可将原始执行时间从约14秒减少到工作站上的~6。这仍然是natan解决方案的三倍慢,对我来说是2秒。
答案 1 :(得分:0)
这是使用meshgrid
,bsxfun
和repmat
的矢量化解决方案:
% 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 秒...