我在MATLAB中迭代一个大型测试矩阵,每次调用第二方专有软件(在MATLAB中运行)。我不能编辑软件源代码。有时,软件会挂起,所以我想在一定时间后退出它,然后继续下一次迭代。
用伪码,我要这么做:
for i = 1:n
output(i) = proprietary_software(input(i));
end如果专有软件花费的时间太长,我如何跳到下一次迭代(并可能保存output(i)='too_long')?
发布于 2015-12-21 23:02:29
您需要从Matlab的另一个实例调用Matlab。另一个Matlab实例将命令和释放控制运行到Matlab的第一个实例,等待其保存结果或达到一定的时间。在这种情况下,它将等待30秒。
您将需要一个额外的功能。确保此函数位于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您需要以这种方式修改原始脚本。
[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我希望这能帮到你。
发布于 2015-12-23 11:06:23
您本质上是要求在MATLAB代码上实现超时的方法。这可能会令人惊讶地难以实现。首先要声明的是,如果所讨论的MATLAB代码不能通过干净地退出或抛出错误来终止自身,那么就不可能在不退出或不杀死所讨论的MATLAB进程的情况下终止该代码。例如,在外部创建的计时器中抛出错误不起作用;错误会被捕获。
因此,首先要提出的问题是:
是否可以使超运行的代码终止自身?
这取决于溢出的原因,也取决于您对源代码的访问:
让我们来处理第一个案子。获得终止代码本身的最简单方法是让它抛出一个错误,如果它超过超时时间,调用方就会捕捉到错误。例如,在“任择议定书”中:
for i = 1:n
tic();
try
output(i) = proprietary_software(input(i));
catch
end
end在超运行循环中的某个位置使用以下代码,或者在循环回调或mex文件中调用:
assert(toc() < 10, 'Timed out');现在是第二个案子。你需要杀死这个MATLAB进程,所以这是一个MATLAB过程,这是有意义的,你已经从你当前的MATLAB会话。您可以使用类似于以下内容的系统调用来完成此操作:
system('matlab -nodisplay -r code_to_run()')虽然在某些情况下,MATLAB进程可以退出(例如调用quit('force')的计时器函数),但最可靠的方法是使用系统调用,使用taskkill (Windows)或kill (Linux/Mac)。
使用产卵和终止超时MATLAB过程的方法的框架可能会像这样工作:
我之所以提供一个草图,只是因为这种方法的全面实现是相当重要的,而且实际上它已经实现了,并且可以在作业工具箱中公开使用。在OP的例子中,使用这个工具箱(有10秒的超时时间),您可以调用:
output = batch_job(@proprietary_software, input(:)', '-timeout', 10);请注意,工具箱要想工作,其根目录需要在启动时位于MATLAB路径上。
https://stackoverflow.com/questions/34326371
复制相似问题