矢量化嵌套循环,其中一个循环变量依赖于另一个循环变量

时间:2014-10-02 18:36:21

标签: matlab for-loop vectorization multidimensional-array

我最近学会了如何矢量化"简单"先前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 ...到目前为止我尝试了什么: jk项的组合(即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)矩阵,而不是用它来对剩余循环进行矢量化的方法。也许我也在错误的道路上......所以我怎样才能对这种类型的循环进行矢量化?

2 个答案:

答案 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%的运行时间,不错......