MATLAB:在ode45中调用feval的替代方法

时间:2011-03-27 04:03:38

标签: matlab loops performance

我希望我的主题在这里。我在这里问,因为它在常见问题页面上说:关于(除其他外)一个软件算法的问题:)所以在这里:

我需要解决一个ODE系统(比如$ \ dot x = A(t)x $。矩阵A可能会改变并在函数调用中作为字符串给出(Calc_EDS_v2('Sys_EDS_a',... )
然后我在循环中使用ode45找到我的x:

function [intervals, testing] = EDS_calc_v2(smA,options,debug)  
[..]
for t=t_start:t_step:t_end)
    [Te,Qe]=func_int(@intQ_2_v2,[t,t+t_step],q);
    q=Qe(end,:);
    [..]
end
[..]

func_int为ode45,@ intQ_2_v2是我的m文件。 q作为起始向量返回到呼叫。正如你所看到的,我只是在intervall [t,t + t_step]上使用ode45。那是因为我的系统矩阵A可以强制ode45使用很多步骤,导致它非常快地击中AbsTol或RelTol。

现在我的A类似于B(t)* Q(t),因此在m文件intQ_2_v2.m中我需要在时间t评估B和Q. 我首先这样做:( v1 -file,所以函数名称不同)

function q=intQ_2_v1(t,X)  
[..] 
B(1)=...; ...   B(4)=...;
Q(1)=...; ...

这自然只是假设A是2x2矩阵。通过这种设置,需要一个基本系统,在10到15秒之间进行计算。

而不是上面我现在使用文件B1.m到B4.m和Q1.m到B4.m(我知道这不是优雅,但我需要在B上使用quadgk而quadgk不支持矩阵函数。)

function q=intQ_2_v2(t,X)  
[..]
global funcnameQ, funcnameB, d
for k=1:d
Q(k)=feval(str2func([funcnameQ,int2str(k)]),t);
B(k)=feval(str2func([funcnameB,int2str(k)]),t);
end
[..]

funcname(字符串)表示B或Q(添加了k),d是系统的维度。

现在我知道它会花费我比第一个版本更多的时间,但我看到计算时间是十倍高! (得到150到160秒)我明白打开4个文件并且每个ode循环估计大约40次是昂贵的...而且我也无法预先评估B和Q,因为ode45使用自适应步长...

有没有办法不使用最后一个循环?

大多数情况下,我对降低计算时间的解决方案感兴趣。我确实有一种感觉,我错过了一些东西......但不能真正把手指放在上面。有一个花了将近三分钟而不是10秒我现在可以在每个testrun之间喝咖啡......(请不​​要告诉我要买一台更快的电脑)

(抱歉这么长的问题)

1 个答案:

答案 0 :(得分:1)

我不确定我完全明白你在这里做了什么,但我可以提供一些提示。

  1. 使用分析器,它将帮助您准确了解瓶颈所在。

  2. 使用feval比直接使用函数句柄要慢,尤其是每次使用str2func构建句柄时。使用全局变量也有所减缓(除非绝对必要,否则避免这些变量是个好习惯)。当重复使用它们时,每个都会加起来(就像这里看起来一样)。将函数句柄存储到单元格数组中的每个mfiles,并将它们直接传递给函数或使用嵌套函数进行优化,以便句柄的单元格数组对正在优化的函数可见。就个人而言,我更喜欢嵌套方法,但如果你在其他地方使用那些mfiles,传递会更好。

  3. 我希望这会让你的运行时恢复到接近第一种方法的效果。请务必告诉我们这是否是问题,或者您是否找到了其他解决方案。