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

Posted

技术标签:

【中文标题】向量化嵌套循环,其中一个循环变量依赖于另一个【英文标题】:vectorizing a nested loop where one loop variable depends on the other 【发布时间】:2014-11-27 19:49:05 【问题描述】:

我最近在我之前问过的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) 矩阵,而不是使用它来向量化剩余循环的方法。也许我也走错了路……那么我怎样才能矢量化这种类型的循环呢?

【问题讨论】:

【参考方案1】:

你很亲密。您提出的矢量化确实遵循 (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% 的运行时间,还不错......

【讨论】:

【参考方案2】:

在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]));

【讨论】:

太棒了!它比@natan 的解决方案更优雅,运行速度快 25%。 @Max 太棒了!很高兴知道这一点! 这个解决方案让我想起了Ramanujan。我完全不知道你到底是怎么得出这个答案的。

以上是关于向量化嵌套循环,其中一个循环变量依赖于另一个的主要内容,如果未能解决你的问题,请参考以下文章

向量化代码并从 pytorch 代码中删除嵌套循环

无法在嵌套循环中使用 pandas 附加更大的数据帧。如何更改为 numpy 向量化?

如何向量化嵌套循环

依赖于 Python 中前一个循环的任意数量的嵌套循环

嵌套循环的 OpenMP SIMD 矢量化

Python中的嵌套循环