这是创建微分方程组的函数trial2
:
function xdot=trial2(t,x)
delta=0.1045;epsilon=0.0048685;
xdot=[x(2);(-delta-epsilon*cos(t))*x(1)-0.7*delta*abs(x(1))];
然后,我尝试使用ode45
解决此问题:
[t,x]=ode45('trial2',[0 10000000],[0;1]);
plot(t,x(:,1),'r');
但是,大约需要15分钟。所以我尝试通过创建一个mex文件来改善运行时间。我找到了ode45
mex等效函数ode45eq.c。然后,我试图解决:
mex ode45eq.c;
[t,x]=ode45eq('trial2',[0 10000000],[0;1]);
plot(t,x(:,1),'r');
但这似乎运行得更慢。可能是什么原因,如何将运行时间提高到2-3分钟?我必须执行很多这些计算。此外,是否值得创建一个独立的C ++文件来更快地解决问题?
此外,我在具有8 GB RAM的Intel i5处理器64位系统上运行此功能。如果我转向更好的16 gb RAM处理器,你认为我能获得多少速度?
答案 0 :(得分:1)
使用当前版本的Matlab,通过将ode45
编译为C / C ++ mex,您不太可能看到任何性能提升。实际上,编译后的版本几乎肯定会慢一些。有一个很好的理由ode45
是用纯Matlab编写的,而不是编译成本机C函数:它必须在每次迭代时调用用Matlab编写的用户函数。另外,Matlab的ode45
是一个非常动态的函数,能够在集成过程中以多种方式与Matlab环境交互(绘制输出函数,事件检测,插值等)。在Matlab中安全处理动态内存分配可能比在C中更直接。
您的C代码通过mexCallMATLAB
调用您的用户功能。此函数为not really meant for repeated calls,特别是如果它们来回传输数据。做你正在尝试做的事情可能需要新的mex API,并可能需要改变Matlab语言。
如果您想要更快的数值积分,您将不得不放弃在Matlab中编写集成函数(即示例中的trial2
)的便利性。您需要"硬编码"您的集成功能并将它们与集成方案本身一起编译。通过详细了解您的问题和良好的编程技巧,您可以编写一个紧密的集成循环,在某些情况下可以实现一个数量级的加速。
最后,您的trial2
函数具有绝对值以及其中的振荡三角函数。这个微分方程是stiff吗?您是否尝试过其他求解器,例如ode15s
?即使在较短的时间内也能比较输出。如果你使用现代的方法将函数句柄而不是字符串传递给ode45
,你可能会发现你获得了一点加速(在我的机器上约为25%):
[t,x] = ode45(@trial2,[0 10000000],[0;1]);
trial2
函数仍然可以在一个单独的M文件中,或者它可以是调用ode45
的同一文件中的子函数(此文件需要是一个函数文件,当然不是剧本。)
答案 1 :(得分:0)
你所做的基本上是用1993年的实现取代今天的实现,你已经证明mathworks在提高ode45求解器的性能方面做得很好。
我认为在这种情况下没有任何改善性能的可能性,你可以假设像ode45
这样的MATLAB这样一个基本部分是以最佳的方式实现的,用其他代码代替它来代替它不是解决方案。使用mex函数可以获得的一切都是减少输入/输出处理的开销,这是以m为单位实现的。可能小于0.1秒的执行时间。