Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MATLAB在函数的最后一行之后花费了很长时间_Matlab_Memory Management_Garbage Collection - Fatal编程技术网

MATLAB在函数的最后一行之后花费了很长时间

MATLAB在函数的最后一行之后花费了很长时间,matlab,memory-management,garbage-collection,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 ([

我有一个函数需要很长时间才能运行。当我分析它时,我发现超过一半的时间(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管理内存方式的一个症状。它在函数返回时解除分配,有时这需要很长时间。该函数确实分配了一些大型(约100万个元素)数组。它也可以处理句柄,但不创建任何新的句柄对象或显式存储句柄。我的问题是:

  • 这肯定是内存管理问题吗
  • 是否有系统的方法来诊断是什么导致此功能出现问题,而不是其他快速返回的功能出现问题
  • 是否有减少MATLAB在函数退出时清理时间的一般提示

  • 你是对的,这似乎是花在你身上的时间。恐怕这是MATLAB的一个基本缺陷,多年来人们就知道了,但MathWorks甚至在最新的MATLAB版本2010b中也没有解决它

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

    不使用任何类型的引用(匿名函数、嵌套函数、句柄类、不使用
    cellfun
    arrayfun
    )可以缓解工作中的问题


    如果你已经达到了MATLAB的“性能障碍”,那么也许你应该简单地改变环境。我不认为从今天开始在MATLAB中创建一个新项目有任何意义,除非您使用SIMULINK。Python为技术计算提供了强大的支持,通过C#您还可以使用MATLAB做很多事情。与MATLAB不同,这两种语言都是真正的编程语言,而且都是免费的。

    一个简单的解决方案是:预先分配大型数组,并将它们作为参数传递给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
    

    我发现了一个可能适用于一般情况的特定问题的修复方法

    在包含句柄对象向量的基本对象上调用了需要很长时间才能退出的函数。当我将基本对象的定义更改为扩展句柄时,我消除了函数关闭时的延迟

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

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

    这对我来说意味着一条一般规则:

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


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

    是MyVal[]优于MelvyMyVar?在退出之前,我尝试过清除除函数return之外的所有变量(使用whos来确定工作区中的变量名),但没有任何帮助。我不知道,请尝试并发布您的发现。您使用的是哪个MATLAB版本?到目前为止,没有MathWorks的工作人员愿意回答这个问题。因此,他们默默地承认这是一个基本的MATLAB设计缺陷。默认情况下,MATLAB不是按值传递的,请参阅以下帖子:。但显然,这个规则并没有应用于值对象。默认情况下,MATLAB的行为是按值传递的。因此,如果存在hadle对象的向量,并且在函数中对该向量进行了更改,则MATLAB需要在退出时处理该更改的后果,即使内部实现没有复制该向量。很可能,这意味着当调用函数时,对象上的引用计数器递增1,而当函数退出时,引用计数器递减1。这应该很快,但可能matlab方案的其他部分,尤其是嵌套和递归对象的部分,就不是这样了。在大多数情况下,这不太可能有帮助。一旦functionCall修改workArr,MATLAB将创建workArr的副本,以存储functionCall中所做的更改。结果是内存消耗翻了一番,执行拷贝时浪费了时间。如果workArr是句柄对象,那么这种方法可能是一种改进。在这种情况下,当然需要进行基准测试。