嵌套循环优化

时间:2013-12-12 03:51:27

标签: matlab loops nested

我真的很难在MATLAB上优化微积分代码。

获得非线性材料的材料属性需要进行大量计算。

此计算需要超过2.4亿步。 它本身相当简单,因为它包含大量的sum。 唯一的问题是数字存储在各种数组和列表中,这有点令人困惑。

以下是原始代码:

Tensor=zeros(3,3,3,3);
for m=1:3
    for n=1:3
        for o=1:3
            for p=1:3
                for x=1:16 
                    for y=1:16
                        for z=1:16 
                            for i=1:3
                                for j=1:3
                                    for k=1:3
                                        for l=1:3
                                            for r=1:3
                                                for s=1:3
                                                    sum=sum+(1/(8*(pi()^2))*P{x,y,z}(i,m)*P{x,y,z}(j,n)*P{x,y,z}(k,o)*P{x,y,z}(l,p)*(TensorC(i,j,k,l)-TensorC0(i,j,r,s))*TensorA(r,s,k,l)*sin(omega(x))*p_omega(x)*p_phi(y)*p_beta(z);
                                                end
                                            end
                                        end                                                    
                                    end
                                end
                            end
                        end
                    end
                end
                Tensor(m,n,o,p)=sum;
            end
        end
    end
end

P{x,y,z}(i,m)是对基础公式的更改(对其他公式相同):i and m确定公式的类型,结果使用xyz个变量。

求和中的所有其他数字都是在数组和张量中拾取的实数。

我试图从最后一个for循环中提取尽可能多的变量,以便尽快计算它们减少操作次数:

Tensor=zeros(3,3,3,3);
CO1=1/(8*(pi()^2));
for m=1:3
    for n=1:3
        for o=1:3
            for p=1:3
            sum=C0_tensor(m,n,o,p);
                for x=1:16
                    CO7=sin(omega(x));
                    CO8=p_omega(x);
                    for y=1:16
                        CO9=p_phi(y);
                        for z=1:16
                            CO10=p_beta(z);
                            for i=1:3
                                CO2=P{x,y,z}(i,m);
                                for j=1:3
                                    CO3=P{x,y,z}(j,n);
                                    for k=1:3
                                        CO4=P{x,y,z}(k,o);
                                        for l=1:3
                                            CO5=P{x,y,z}(l,p);
                                            CO6=TensorC(i,j,k,l);
                                            for r=1:3
                                                for s=1:3
                                                    CO11=TensorC0(i,j,r,s);
                                                    CO12=TensorA(r,s,k,l);
                                                    sum=sum+CO1*CO2*CO3*CO4*CO5*(CO6-CO11)*CO12*CO7*CO8*CO9*CO10;
                                                end
                                            end
                                        end                                                    
                                    end
                                end
                            end
                        end
                    end
                end
                Tensor(m,n,o,p)=sum;
            end
        end
    end
end

但是,计算太长了。

我没有看到任何平行化或矢量化计算的方法......

从一个数组或一个矩阵中检索一个特定值的操作似乎非常慢......

你认为我应该构建一个包含所有值的巨大张量而不是使用倍数吗?

1 个答案:

答案 0 :(得分:1)

你不应该使用sum作为变量名,因为你用相同的名称覆盖了有用的函数。

在此处仅使用内部循环,您计算每个rs的单个值,该值将添加到您的输出值中:

  for r=1:3
         for s=1:3
              CO11=TensorC0(i,j,r,s);
              CO12=TensorA(r,s,k,l);
              sum=sum+CO1*CO2*CO3*CO4*CO5*(CO6-CO11)*CO12*CO7*CO8*CO9*CO10;
         end
  end

然而,您可以立即将C011 / C012作为3 x 3矩阵,做一个总和,然后将其添加到您的输出: (在此处将sum更改为out,请注意。*而不是*在适当的位置):

C011 = squeeze(TensorCO(i,j,:,:));
C012 = squeeze(TensorCO(:,:,k,l));
s = CO1*CO2*CO3*CO4*CO5*(CO6-CO11).*CO12*CO7*CO8*CO9*CO10;
out = out + sum(s(:));

此外,当你这样做时:

CO7=sin(omega(x));
CO8=p_omega(x);

(在后面的等式中就是C07 * C08) - 你不需要为每个n,m,p.重新计算sin(omega(x)),这样就可以完全取出循环。

预先计算sin并乘以p_omega(外部循环):

omega78 = sin(omega).*p_omega;

然后只需检索x循环中的值C78 = omega78(x),然后使用它而不是C07*C08