首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在给定的时间后突破专有工具箱

在给定的时间后突破专有工具箱
EN

Stack Overflow用户
提问于 2015-12-17 03:58:21
回答 2查看 509关注 0票数 10

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

用伪码,我要这么做:

代码语言:javascript
复制
for i = 1:n
    output(i) = proprietary_software(input(i));
end

如果专有软件花费的时间太长,我如何跳到下一次迭代(并可能保存output(i)='too_long')?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-12-21 23:02:29

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

您将需要一个额外的功能。确保此函数位于Matlab路径上。

代码语言:javascript
复制
function proprietary_software_caller(input)
    hTic=tic;
    output=proprietary_software(input);
    hToc=toc(hTic);
    if hToc<30
       save('outfile.mat','output');
    end
    exit;
end

您需要以这种方式修改原始脚本。

代码语言:javascript
复制
[status,firstPID] = str2double(system('for /f "tokens=2 delims=," %F in (''tasklist /nh /fi "imagename eq Matlab.exe" /fo csv) do @echo %~F'')'));

for i = 1:n
    inputStr=num2str(input(i));
    system(['matlab.exe -nodesktop -r proprietary_software_caller\(',inputStr,'\)&']);
    hTic=tic;
    hToc=toc(hTic);
    while hToc<30 || ~(exist('outfile.mat','file')==2)
       hToc=toc(hTic);
    end
    if hToc>=30
        output(i)= 'too_long';
        [status,allPIDs]=str2double(system('for /f "tokens=2 delims=," %F in (''tasklist /nh /fi "imagename eq Matlab.exe" /fo csv) do @echo %~F'')'));
        allPIDs(allPIDs==firstPID)=[];
        for a=1:numel(allPIDs)
           [status,cmdout]=system(['taskkill /F /pid ' sprintf('%i',allPIDs(a))]);
        end
    elseif exist('outfile.mat','file')==2
        loadedData=load('outfile.mat');
        output(i)=loadedData.output;
        delete('outfile.mat');
    end
end

我希望这能帮到你。

票数 1
EN

Stack Overflow用户

发布于 2015-12-23 11:06:23

您本质上是要求在MATLAB代码上实现超时的方法。这可能会令人惊讶地难以实现。首先要声明的是,如果所讨论的MATLAB代码不能通过干净地退出或抛出错误来终止自身,那么就不可能在不退出或不杀死所讨论的MATLAB进程的情况下终止该代码。例如,在外部创建的计时器中抛出错误不起作用;错误会被捕获。

因此,首先要提出的问题是:

是否可以使超运行的代码终止自身?

这取决于溢出的原因,也取决于您对源代码的访问:

  • 如果程序被困在一个无限(或非常长时间运行的)循环中,无论是在MATLAB代码中,还是在有源代码的mex文件中,或者在每次迭代时调用用户定义的回调,那么您都可以得到这些代码来终止自己。
  • 如果程序被卡在MATLAB内置的文件中,或者没有源代码的p代码文件或mex文件中,并且不支持定期调用回调,那么就不可能让代码自行终止。

让我们来处理第一个案子。获得终止代码本身的最简单方法是让它抛出一个错误,如果它超过超时时间,调用方就会捕捉到错误。例如,在“任择议定书”中:

代码语言:javascript
复制
for i = 1:n
    tic();
    try
        output(i) = proprietary_software(input(i));
    catch
    end
end

在超运行循环中的某个位置使用以下代码,或者在循环回调或mex文件中调用:

代码语言:javascript
复制
assert(toc() < 10, 'Timed out');

现在是第二个案子。你需要杀死这个MATLAB进程,所以这是一个MATLAB过程,这是有意义的,你已经从你当前的MATLAB会话。您可以使用类似于以下内容的系统调用来完成此操作:

代码语言:javascript
复制
system('matlab -nodisplay -r code_to_run()')

虽然在某些情况下,MATLAB进程可以退出(例如调用quit('force')的计时器函数),但最可靠的方法是使用系统调用,使用taskkill (Windows)或kill (Linux/Mac)。

使用产卵和终止超时MATLAB过程的方法的框架可能会像这样工作:

  1. 使用系统调用,从MATLAB会话启动一个或多个新的MATLAB进程,运行所需的代码。
  2. 使用文件系统或内存映射文件在MATLAB处理函数输入、循环进度、输出、进程ids和超时时间之间进行通信。
  3. 使用原始的MATLAB进程检查未达到的超时时间,如果是,则终止所讨论的进程并实例化一个新的进程。
  4. 使用原始的MATLAB进程收集函数输出(无论是从文件系统还是从内存映射文件)并退出。工人应在没有剩余工作时终止工作。

我之所以提供一个草图,只是因为这种方法的全面实现是相当重要的,而且实际上它已经实现了,并且可以在作业工具箱中公开使用。在OP的例子中,使用这个工具箱(有10秒的超时时间),您可以调用:

代码语言:javascript
复制
output = batch_job(@proprietary_software, input(:)', '-timeout', 10);

请注意,工具箱要想工作,其根目录需要在启动时位于MATLAB路径上。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34326371

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档