【问题标题】:ode45 mex file runs slowode45 mex 文件运行缓慢
【发布时间】:2014-07-20 13:05:26
【问题描述】:

这是创建微分方程组的函数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,你认为我能获得多少速度提升?

【问题讨论】:

  • 关于更多内存/更好cpu的想法。内存使用率非常低,这无济于事。求解器主要在单个内核上运行,因此并行运行多个实例可能是另一种选择?更好的 CPU 会有所帮助,但请记住,只使用一个内核。根据您当前的 CPU,它可能不值得升级。

标签: performance matlab mex


【解决方案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 相同的文件中的子函数(此文件必须是函数文件,而不是当然)。

【讨论】:

    【解决方案2】:

    您所做的基本上是将今天的实现替换为 1993 年的实现,您已经证明 mathworks 在提高 ode45 求解器的性能方面做得很好。

    在这种情况下,我看不到任何提高性能的可能性,您可以假设像 ode45 这样的 MATLAB 的基本部分以最佳方式实现,用其他一些代码替换它来混合它不是解决方案。使用 mex 函数可以获得的一切都是削减在 m 中实现的输入/输出处理的开销。执行时间大概不到 0.1 秒。

    【讨论】:

      猜你喜欢
      • 2021-11-25
      • 2020-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多