Matlab 在给定时间后从专用工具箱中跳出

Matlab 在给定时间后从专用工具箱中跳出,matlab,timeout,break,Matlab,Timeout,Break,我在MATLAB中迭代一个大型测试矩阵,每次都调用第二方专有软件(在MATLAB中运行)。我无法编辑软件源代码。有时候,软件挂起,所以我想在一段时间后退出它,继续下一次迭代 在伪代码中,我这样做: for i = 1:n output(i) = proprietary_software(input(i)); end 如果专有软件花费的时间太长,我如何跳到下一次迭代(并可能保存输出(I)=“太长”)呢?您需要从另一个Matlab实例调用Matlab。Matlab的另一个实例将运行命令并将

我在MATLAB中迭代一个大型测试矩阵,每次都调用第二方专有软件(在MATLAB中运行)。我无法编辑软件源代码。有时候,软件挂起,所以我想在一段时间后退出它,继续下一次迭代

在伪代码中,我这样做:

for i = 1:n
    output(i) = proprietary_software(input(i));
end

如果专有软件花费的时间太长,我如何跳到下一次迭代(并可能保存
输出(I)=“太长”
)呢?

您需要从另一个Matlab实例调用Matlab。Matlab的另一个实例将运行命令并将控制释放到Matlab的第一个实例以等待,同时保存结果或达到某个时间。在这种情况下,它将等待30秒

您将需要1个附加功能。确保此函数位于Matlab路径上

function proprietary_software_caller(input)
    hTic=tic;
    output=proprietary_software(input);
    hToc=toc(hTic);
    if hToc<30
       save('outfile.mat','output');
    end
    exit;
end
功能专用软件调用方(输入)
hTic=tic;
输出=专有软件(输入);
hToc=总有机碳(hTic);

如果hToc您实际上是在寻求一种在MATLAB代码上实现超时的方法。这可能会令人惊讶地难以实现。首先要说明的是,如果所讨论的MATLAB代码无法通过干净地退出或抛出错误来终止自身,则可以在不退出或终止所讨论的MATLAB进程的情况下终止代码。例如,在外部创建的计时器中抛出错误不起作用;错误被发现了

因此,第一个问题是:

是否可以使过度运行的代码自行终止

这取决于过度运行的原因,以及您对源代码的访问:

  • 如果程序陷入无限(或长时间运行)循环中,无论是在MATLAB代码中,还是在mex文件中,您有源代码,或者在每次迭代中调用用户定义的回调,那么您可以让该代码自行终止
  • 如果程序卡在MATLAB内置程序中,或者卡在没有源代码的p代码文件或mex文件中,并且不支持定期调用回调,那么您就不可能让代码自行终止
让我们谈谈第一个案例。让代码自行终止的最简单方法是让它抛出一个错误,如果该错误超过超时时间,则会被调用方捕获。例如,在OP的情况下:

for i = 1:n
    tic();
    try
        output(i) = proprietary_software(input(i));
    catch
    end
end
在过度运行的循环中,或在循环回调或mex文件中调用以下代码:

assert(toc() < 10, 'Timed out');
虽然MATLAB进程在某些情况下可能会自动退出(例如,调用
quit('force')
)的计时器函数),但杀死MATLAB进程最可靠的方法是使用系统调用,使用
taskkill
(Windows)或
kill
(Linux/Mac)

使用繁殖和杀死超时MATLAB进程的方法的框架可能如下所示:

  • 使用系统调用,从MATLAB会话启动一个或多个新的MATLAB进程,运行所需的代码
  • 使用文件系统或内存映射文件在MATLAB进程之间通信函数输入、循环进度、输出、进程ID和超时时间
  • 使用原始MATLAB进程检查超时时间是否未达到,或者如果达到,则终止有问题的进程并实例化一个新进程
  • 使用原始的MATLAB过程收集函数输出(来自文件系统或内存映射文件)并退出。工人应在没有剩余工作时终止工作
  • 我之所以提供一个草图,仅仅是因为这个方法的完整工作实现是相当复杂的,事实上它已经实现了,并且可以在中公开获得。在OP的情况下,使用此工具箱(有10秒的超时),您可以调用:

    output = batch_job(@proprietary_software, input(:)', '-timeout', 10);
    

    请注意,要使工具箱正常工作,其根目录必须在启动时位于MATLAB路径上

    我想你可以用电脑来做。我要试试看我是否能让一些代码正常工作…嗯。。。我希望您可以将其放入
    try
    -
    catch
    块中,让计时器对象抛出错误。但计时器对象回调函数似乎以某种方式发生(可能是另一个线程),它抛出的错误未被
    try
    -
    catch
    识别。:/。也许你可以尝试一些线程,但我认为这将是非常混乱的:你如何调用外部软件?您使用的是
    system
    或等效软件,还是通过dll或jar文件?您可以将tic/toc解决方案与try-catch块结合使用吗?你可以抛出一个错误,让catch块来处理它,可能会将它全部封装在一个while-true风格的循环中以保持事情的运行?为什么你不能在MATLAB的一个实例中设置
    tic/toc
    ,或者,换句话说,为什么你需要
    system
    调用?在调试完上面的代码之后,我主要是通过一个最小的工作示例来实现的。然而,有一个问题;即使主脚本在MATLAB的一个实例花费的时间太长时会继续运行,该实例仍会继续运行。因此,最终它可能会抛出一个与当前迭代不对应的
    outfile.mat
    。Delyle,您可以始终在第一个函数中添加一个tic/toc。我已经更新了我的答案。@adrian
    系统
    调用用于启动Matlab的另一个实例以自动化循环。这将允许脚本在后台调用函数。@Adrian,原因是Matlab会被Delyle使用的专有软件卡住。您可以按住ctrl-C键并跳出它,然后继续循环,但这不会有效。在Matlab中的函数完成之前,不能中断函数。唯一的其他选择将涉及并行计算工具箱或使用此解决方案中的并行化技巧
    system('matlab -nodisplay -r code_to_run()')
    
    output = batch_job(@proprietary_software, input(:)', '-timeout', 10);