MATLAB在函数的最后一行之后需要很长时间

时间:2010-11-24 14:55:41

标签: matlab memory-management garbage-collection

我有一个需要很长时间才能运行的功能。当我对它进行分析时,我发现超过一半的时间(50秒中的26个)没有计入逐行时序故障,我可以证明在函数完成运行之后但在它返回控制之前花费的时间通过以下方法:

ts1 = tic;
disp ('calling function');
functionCall(args);
disp (['control returned to caller - ', num2str(toc(ts1))]); 

我调用的函数的第一行是ts2 = tic,最后一行是

disp (['last line of function- ', num2str(toc(ts2))]);

结果是

  

调用函数

     

最后一行功能 - 24.0043

     

控制权返回给来电者 - 49.857

在互联网上闲聊,我认为这是MATLAB管理内存的方式的症状。它在函数返回时释放,有时这需要很长时间。该函数确实分配了一些大的(~1百万个元素)数组。它也适用于句柄,但不会显式创建任何新的句柄对象或存储句柄。我的问题是:

  1. 这肯定是内存管理问题吗?
  2. 是否有任何系统的方法来诊断导致此功能出现问题的原因,而不是快速返回的其他问题?
  3. 是否有减少MATLAB在功能退出时清理的时间的一般提示?

3 个答案:

答案 0 :(得分:4)

你是对的,似乎是花在garbage collection上的时间。我担心它是一个基本的MATLAB缺陷,它已经知道多年,但MathWorks即使在最新的MATLAB版本2010b中也没有解决它。

您可以尝试在离开函数之前手动将变量设置为[] - 即手动执行垃圾收集。此技术还有助于against memory以前的MATLAB版本中的泄漏。现在,MATLAB将花费时间不在end上,而是在myVar=[];

您可以在没有任何类型的引用的情况下缓解问题 - 匿名函数,嵌套函数,句柄类,不使用cellfunarrayfun

如果你已经到达了MATLAB的“性能障碍”,那么你应该只是改变环境。除非您使用的是SIMULINK,否则我从今天开始在MATLAB中看到一个新项目没有任何意义。 Python可用于技术计算,使用C#,您也可以使用free libraries做很多事情。它们都是真正的编程语言,并且是免费的,与MATLAB不同。

答案 1 :(得分:2)

我发现了一个可能适用于我的具体问题的修复程序。

在包含句柄对象向量的基本对象上调用了需要很长时间才能退出的函数。当我改变基本对象的定义以扩展句柄时,我消除了函数结束时的滞后。

我认为发生的事情是:当我将基本对象传递给我的函数时,它创建了该对象的副本(默认情况下,MATLAB是按值传递的)。这不需要花费很多时间,但是当函数退出时,它会破坏对象副本,这会导致它查看句柄对象的向量,以确保没有任何需要清理的孤儿。我相信正是这个操作花了很长时间才使用MATLAB。

当我更改了传递给句柄的对象时,在函数工作区中没有复制,因此最后不需要清理对象。

这对我来说是一般规则:

如果函数在退出时需要很长时间来清理其工作区,并且您按值传递了大量数据或复杂结构,请尝试在句柄对象中封装该函数的参数

这样可以避免重复,从而避免在退出时进行耗时的清理工作。缺点是你的函数现在可以意外地改变你的输入,因为MATLAB没有能力声明参数const,就像在c ++中一样。

答案 2 :(得分:0)

一个简单的解决方法可能是:预分配大型数组并将它们作为args传递给functionCall()。这会将释放问题移回给functionCall()的调用者,但可能是你比其父调用函数更频繁地调用functionCall,在这种情况下,这将加速你的代码。

workArr = zeros(1,1e6); % allocate once
...
functionCall(args,workArr); % call with extra argument
...
functionCall(args,wokrArr); % call again, no realloc of workArr needed
...

在functionCall中你可以负责初始化和/或重新设置workArr,例如

[workArr(:)] = 0; % reset work array