我每次都在MATLAB中迭代一个大的测试矩阵并调用第二方专有软件(在MATLAB中运行)。我无法编辑软件源代码。有时候,软件会挂起,所以我想在一段时间后退出它并继续下一次迭代。
在伪代码中,我这样做:
for i = 1:n
output(i) = proprietary_software(input(i));
end
如果专有软件耗时太长,我怎样才能跳到下一次迭代(并可能保存output(i)='too_long'
)?
答案 0 :(得分:1)
您需要从另一个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
您需要以这种方式修改原始脚本
[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 :(得分:1)
您实际上是在寻求一种在MATLAB代码上实现超时的方法。实施起来可能会非常棘手。首先要说明的是,如果有问题的MATLAB代码无法自行终止,无论是通过干净地退出还是抛出错误,那么不可以在不退出或终止MATLAB进程的情况下终止代码题。例如,在外部创建的计时器中抛出错误不起作用;错误被捕获。
首先要问的问题是:
是否可以使超限代码自行终止?
这取决于过度运行的原因,以及您对源代码的访问:
让我们解决第一个案例。让代码终止自身的最简单方法是让它抛出一个错误,如果它超过了超时时间,它会被调用者捕获。例如。在OP的案例中:
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')
的定时器函数),但是杀死MATLAB过程的最可靠方法是使用系统调用,使用taskkill
(Windows)或kill
(Linux / Mac)。
使用产卵方法和杀死超时MATLAB流程的框架可能会这样:
我之所以提供草图只是因为这种方法的完整工作实施得到了公平的参与,事实上它已经实施并在batch_job toolbox中公开提供。在OP的情况下,使用此工具箱(超时10秒),您可以致电:
output = batch_job(@proprietary_software, input(:)', '-timeout', 10);
请注意,要使工具箱正常工作,其根目录必须在启动时位于MATLAB路径上。