亲爱的堆栈溢出社区。是否可以在Matlab中提高此代码的速度?我可以使用向量化吗?请注意,我必须在每个循环中使用“ vpasolve”或“ fsolve”功能。
以下是使用双循环调用该函数的代码:
for i=1:1000
for j=1:1000
SilA(i,j)=SolW(i,j);
end
end
这是上面的代码调用的函数。我可以向量化w,xi的输入并使代码运行得更快吗?
function [ffw] = SolW(w,xi)
format long e;
z=0;mm=0.46;sop=80;
epit=0.1;voP=80.;
rho=2.1;aposC=0.1;aposD=0.1;
parEh=0.2*10^6;parEv=0.2*10^6;parGv=0.074*10^6;
parpos=0.35;hp=0.2;Ep=30*10^6;
parposV=0.20;ll=0.15;dd=2*ll;
C11=(parEh*(parEv-parEh*parpos^2)/((1+parpos)*(parEv-parEv*parpos-2*parEh*parpos^2)))*(1+2*1i*aposD);
C13=(parEh*parEv*parpos/((parEv-parEv*parpos-2*parEh*parpos^2)))*(1+2*1i*aposD);
C33=((1-parpos)*parEv^2/(parEv-parEv*parpos-2*parEh*parpos^2))*(1+2*1i*aposD);
C44=parGv*(1+2*1i*aposD);
DD=(Ep*hp^3)/(12*(1-parposV^2));
a1=C44;
a2=C33;
c1=(C13+C44)*1i*xi;
c2=(C13+C44)*1i*xi;
b1=rho*w^2-C11*xi^2;
b2=rho*w^2-C44*xi^2;
syms xr
rsol=vpasolve((a1*xr+b1).*(a2*xr+b2)-c1*c2*xr==0,xr);
rsol=eval(rsol);
r=[-sqrt(rsol)];
r1=r(1,:);
r2=r(2,:);
Fdf1=sop*sqrt(2*pi/(1i*epit*xi))*exp(1i*(xi*voP+w)^2/(2*epit*xi));
BC11=C44*(r1-1i*xi*c2*r1/(a2*r1^2+b2));
BC21=(C13*1i*xi)-((C33*c2*r1^2)/(a2*r1^2+b2))+(DD*xi^4-mm*w^2+1i*aposC*w)*c2*r1/(a2*r1^2+b2);
BC12=C44*(r2-1i*xi*c2*r2/(a2*r2^2+b2));
BC22=(C13*1i*xi)-((C33*c2*r2^2)/(a2*r2^2+b2))+(DD*xi^4-mm*w^2+1i*aposC*w)*c2*r2/(a2*r2^2+b2);
syms As1 As2;
try
[Ass1,Ass2]=vpasolve(BC11*As1+BC12*As2==0,BC21*As1+BC22*As2+Fdf1==0,As1,As2);
A1=eval(Ass1);
A2=eval(Ass2);
catch
A1=0.0;
A2=0.0;
end
Bn1=-(c2*r1/(a2*r1^2+b2))*A1;
Bn2=-(c2*r2/(a2*r2^2+b2))*A2;
ffw=Bn1*exp(r1*z)+Bn2*exp(r2*z);
end
答案 0 :(得分:1)
函数中的所有内容,但对vpasolve
和try....
的调用都可以向量化。
首先,所有这些都不取决于w
或xi
,因此只能计算一次:
format long e;
z=0;mm=0.46;sop=80;
epit=0.1;voP=80.;
rho=2.1;aposC=0.1;aposD=0.1;
parEh=0.2*10^6;parEv=0.2*10^6;parGv=0.074*10^6;
parpos=0.35;hp=0.2;Ep=30*10^6;
parposV=0.20;ll=0.15;dd=2*ll;
C11=(parEh*(parEv-parEh*parpos^2)/((1+parpos)*(parEv-parEv*parpos-2*parEh*parpos^2)))*(1+2*1i*aposD);
C13=(parEh*parEv*parpos/((parEv-parEv*parpos-2*parEh*parpos^2)))*(1+2*1i*aposD);
C33=((1-parpos)*parEv^2/(parEv-parEv*parpos-2*parEh*parpos^2))*(1+2*1i*aposD);
C44=parGv*(1+2*1i*aposD);
DD=(Ep*hp^3)/(12*(1-parposV^2));
a1=C44;
a2=C33;
据我所知,eval
很慢,我很确定您不需要它:
rsol=eval(rsol);
这里是矢量化的一个示例。您应该首先使用meshgrid生成所有索引组合,然后使用.
注意到matlab使用元素明智的操作:
[I, J] = meshgrid(1:1000, 1:1000)
c1=(C13+C44)*1i.*xi;
c2=(C13+C44)*1i.*xi;
b1=rho.*w.^2 - C11.*xi.^2;
b2=rho.*w.^2-C44.*xi.^2;
但是您将无法向量化 vpasolve
和try....
,而不能将其更改为其他内容。 vpasolve
可能是您计算的瓶颈(使用matlab profiler 进行验证),因此如上所述的优化可能不会大大减少您的计算时间。
那么您有几种解决方案:
parfor
来并行化计算,这取决于您的体系结构,可以使速度提高4倍左右。vpasolve
要快得多。 这可能会为您带来最快的加速速度(猜测因子10 -100吗?) 希望这会有所帮助
答案 1 :(得分:0)
在上面的程序中,所有内容都可以向量化为上述@beesleep。 例如:
[I, J] = meshgrid(1:1000, 1:1000)
c1=(C13+C44)*1i.*xi;
c2=(C13+C44)*1i.*xi;
b1=rho.*w.^2 - C11.*xi.^2;
b2=rho.*w.^2-C44.*xi.^2;
vpasolve部分,即
syms xr
rsol=vpasolve((a1*xr+b1).*(a2*xr+b2)-c1*c2*xr==0,xr);
rsol=eval(rsol);
r=[-sqrt(rsol)];
r1=r(1,:);
r2=r(2,:);
也可以使用fsolve进行矢量化处理,如下所示:
fun=@(Xr) (a1.*Xr+b1).*(a2.*Xr+b2)-c1.*c2.*Xr
x01=-ones(2*Nxi);
x02=ones(2*Nxi);
options.Algorithm= 'trust-region-reflective'
options.JacobPattern=speye(4*Nxi^2);
options.PrecondBandWidth=0;
[rsol1]=fsolve(fun,x01,options);
[rsol2]=fsolve(fun,x02,options);
另一部分,即
syms As1 As2;
try
[Ass1,Ass2]=vpasolve(BC11*As1+BC12*As2==0,BC21*As1+BC22*As2+Fdf1==0,As1,As2);
A1=eval(Ass1);
A2=eval(Ass2);
catch
A1=0.0;
A2=0.0;
end
由于包含线性方程,并且在每一行中都有两个从属方程可以被求解,如下所示:
funAB1=@(As1) BC11.*As1+BC12.*((-Fdf2-BC21.*As1)./BC22);
x0AB=ones(2*Nxi)+1i*ones(2*Nxi);
options.Algorithm= 'trust-region-reflective';
options.JacobPattern=speye(4*Nxi^2);
options.PrecondBandWidth=0;
[A1]=fsolve(funAB1,x0AB,options);
A2=((-Fdf2-BC21.*A1)./BC22);
但是,两者都可以通过解析来解决,即
AAr=a1.*a2;
BBr=a1.*b2+b1.*a2-c1.*c2;
CCr=b1.*b2;
Xr1=(-BBr+sqrt(BBr^.2-4.*AAr.*CCr))./(2.*AAr);
Xr2=(-BBr-sqrt(BBr^.2-4.*AAr.*CCr))./(2.*AAr);
r1=-sqrt(Xr1(:,:));
r2=-sqrt(Xr2(:,:));