当 a 中出现内存不足错误时parfor
,有没有办法只杀死一个 Matlab 从站来释放一些内存而不是让整个脚本终止?
这是在 a 中发生内存不足错误时默认发生的情况parfor
:脚本终止,如下面的屏幕截图所示。
我希望有一种方法可以杀死一个奴隶(即从中删除一个工人parpool
)或停止使用它来释放尽可能多的内存:
当 a 中出现内存不足错误时parfor
,有没有办法只杀死一个 Matlab 从站来释放一些内存而不是让整个脚本终止?
这是在 a 中发生内存不足错误时默认发生的情况parfor
:脚本终止,如下面的屏幕截图所示。
我希望有一种方法可以杀死一个奴隶(即从中删除一个工人parpool
)或停止使用它来释放尽可能多的内存:
如果您在主进程中出现内存不足,则没有机会解决此问题。对于从站内存不足,应该这样做:
代码的简单想法:使用丢失的数据一次又一次地重新启动 parfor,直到获得所有结果。如果一次迭代失败,则写入一个标志(文件),让所有迭代在第一个错误发生时立即抛出错误。这样我们就可以“脱离循环”,而不会浪费时间产生其他内存不足。
%Your intended iterator
iterator=1:10;
%flags which indicate what succeeded
succeeded=false(size(iterator));
%result array
result=nan(size(iterator));
FLAG='ANY_WORKER_CRASHED';
while ~all(succeeded)
fprintf('Another try\n')
%determine which iterations should be done
todo=iterator(~succeeded);
%initialize array for the remaining results
partresult=nan(size(todo));
%initialize flags which indicate which iterations succeeded (we can not
%throw erros, it throws aray results)
partsucceeded=false(size(todo));
%flag indicates that any worker crashed. Have to use file based
%solution, don't know a better one. #'
delete(FLAG);
try
parfor falseindex=1:sum(~succeeded)
realindex=todo(falseindex);
try
% The flag is used to let all other workers jump out of the
% loop as soon as one calculation has crashed.
if exist(FLAG,'file')
error('some other worker crashed');
end
% insert your code here
%dummy code which randomly trowsexpection
if rand<.5
error('hit out of memory')
end
partresult(falseindex)=realindex*2
% End of user code
partsucceeded(falseindex)=true;
fprintf('trying to run %d and succeeded\n',realindex)
catch ME
% catch errors within workers to preserve work
partresult(falseindex)=nan
partsucceeded(falseindex)=false;
fprintf('trying to run %d but it failed\n',realindex)
fclose(fopen(FLAG,'w'));
end
end
catch
%reduce poolsize by 1
newsize = matlabpool('size')-1;
matlabpool close
matlabpool(newsize)
end
%put the result of the current iteration into the full result
result(~succeeded)=partresult;
succeeded(~succeeded)=partsucceeded;
end
经过相当多的研究和大量的试验和错误,我想我可能有一个体面、紧凑的答案。你要做的是:
memory
,但我喜欢直接设置它。memory
在您的循环内调用parfor
,该循环返回该特定工作人员的内存信息。parfor
,您可能需要任务delete
或cancel
工作人员。我已经验证,当远程集群上的每个工作人员有一个任务时,它可以与下面的代码一起使用。在内容的开头插入以下代码parfor
。根据需要进行调整。
memLimit = 280000000; %// This doesn't have to be in parfor. Everything else does.
memData = memory;
if memData.MemUsedMATLAB > memLimit
task = getCurrentTask();
cancel(task);
end
享受!(顺便说一句,有趣的问题。)
另一个要考虑的选项是,从 R2013b 开始,您可以打开一个'SpmdEnabled'
设置为的并行池false
- 这允许 MATLAB 工作进程在不关闭整个池的情况下终止 - 请参阅此处的文档http://www.mathworks.co.uk /help/distcomp/parpool.html。当然,您仍然需要以某种方式安排关闭工人。