3

当 a 中出现内存不足错误时parfor,有没有办法只杀死一个 Matlab 从站来释放一些内存而不是让整个脚本终止?

这是在 a 中发生内存不足错误时默认发生的情况parfor:脚本终止,如下面的屏幕截图所示。

在此处输入图像描述

我希望有一种方法可以杀死一个奴隶(即从中删除一个工人parpool)或停止使用它来释放尽可能多的内存:

在此处输入图像描述

4

3 回答 3

3

如果您在主进程中出现内存不足,则没有机会解决此问题。对于从站内存不足,应该这样做:

代码的简单想法:使用丢失的数据一次又一次地重新启动 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
于 2014-06-17T18:30:01.383 回答
2

经过相当多的研究和大量的试验和错误,我想我可能有一个体面、紧凑的答案。你要做的是:

  1. 声明一些最大内存值。您可以使用 MATLAB 函数动态设置它memory,但我喜欢直接设置它。
  2. memory在您的循环内调用parfor,该循环返回该特定工作人员的内存信息。
  3. 如果worker使用的内存超过阈值,则取消worker正在处理的任务。现在,这里有点棘手。根据您使用的方式parfor,您可能需要任务deletecancel工作人员。我已经验证,当远程集群上的每个工作人员有一个任务时,它可以与下面的代码一起使用。

在内容的开头插入以下代码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

享受!(顺便说一句,有趣的问题。)

于 2014-06-17T19:58:58.750 回答
2

另一个要考虑的选项是,从 R2013b 开始,您可以打开一个'SpmdEnabled'设置为的并行池false- 这允许 MATLAB 工作进程在不关闭整个池的情况下终止 - 请参阅此处的文档http://www.mathworks.co.uk /help/distcomp/parpool.html。当然,您仍然需要以某种方式安排关闭工人。

于 2014-06-18T07:33:03.420 回答