我最近学会了如何矢量化"简单"先前question我曾问过嵌套循环。但是,现在我也尝试对以下循环进行矢量化
A=rand(80,80,10,6,8,8);
I=rand(size(A1,3),1);
C=rand(size(A1,4),1);
B=rand(size(A1,5),1);
for i=1:numel(I)
for v=1:numel(C)
for j=1:numel(B)
for k=1:j
A(:,:,i,v,j,k)= A(:,:,i,v,j,k)*I(i)*C(v)*B(j)*((k-1>0)+1);
end
end
end
end
所以现在k
取决于j
...到目前为止我尝试了什么:
j
和k
项的组合(即B(j)*((k-1>0)+1)
给出了一个三角矩阵,我设法独立地进行矢量化:
B2=tril([ones(8,1)*B']');
B2(2:end,2:end)=2*B2(2:end,2:end);
但是这给了我正确的(j,k)矩阵,而不是用它来对剩余循环进行矢量化的方法。也许我也在错误的道路上......所以我怎样才能对这种类型的循环进行矢量化?
答案 0 :(得分:11)
在前一个问题的已接受解决方案的one of your comments中,您提到基于bsxfun(@times,..,permute..)
的连续代码更快。如果是这种情况,您也可以在这里使用类似的方法。以下是与tril
-
B1 = tril(bsxfun(@times,B,[1 ones(1,numel(B)-1).*2]));
v1 = bsxfun(@times,B1, permute(C,[3 2 1]));
v2 = bsxfun(@times,v1, permute(I,[4 3 2 1]));
A = bsxfun(@times,A, permute(v2,[5 6 4 3 1 2]));
答案 1 :(得分:2)
你很亲密。你提出的矢量化确实遵循(j,k)逻辑,但是在tril
中,在循环没有进入的地方添加零。使用上一个问题的解决方案(@ david' s)并不完整,因为它会将所有元素(包括循环不进入的零值元素)相乘。我的解决方案是找到这些零元素并用1替换它们(如此简单):
从您的代码开始:
B2=tril([ones(8,1)*B']');
B2(2:end,2:end)=2*B2(2:end,2:end);
并遵循上一个问题中显示的矢量化:
s=size(A);
[b,c,d]=ndgrid(I,C,B2);
F=b.*c.*d;
F(F==0)=1; % this is the step that is important for your case.
A=reshape(A,s(1),s(2),[]);
A=bsxfun(@times,A,permute(F(:),[3 2 1]));
A=reshape(A,s);
对于问题中使用的A
大小,这减少了大约50%的运行时间,不错......