我在Matlab中有一种奇怪的错误。
metr = cell(1,length(paths));
parfor i = 1:length(paths)
try
a = read(path{i});
catch err
continue;
end
metr{i} = dosomething(a);
end
以上代码作为普通循环正常工作并捕获两个错误并继续。如果我使它成为一个parfor
循环,那么当它捕获一个错误时,它会从一开始就再次疯狂地运行for循环,最后会因为找不到变量metr
而崩溃。 / p>
但是,如果我按如下方式重写它,我不会收到任何错误,并且parfor
循环有效,无论我是否留下continue
语句:
metr = cell(1,length(paths));
parfor i = 1:length(paths)
try
a = read(path{i});
errB = 0;
catch err
errB = 1;
continue;
end
if ~errB
metr{i} = dosomething(a);
end
end
有谁知道发生了什么?似乎它在continue
语句之后继续执行。我认为parfor循环中不支持break;
且continue
有效。
我很困惑......
P.S。错误:
对于'metr',工人抛出了UndefinedFunction错误 这可能是因为包含'metr'的文件 工人无法进入。
编辑:好的,我发现谁有错。似乎如果我从err
行删除catch err
变量,它突然正常工作!我仍然不知道为什么将错误分配给变量会使循环变得疯狂。
答案 0 :(得分:0)
我仔细研究了你的代码。我无法准确再现您的错误,但并行计算工具箱存在问题并继续。在Matlab 2013a中,以下几行崩溃概率为50%
metr = cell(1,100);
parfor ix = 1:100
disp(ix);
try
if rand<0.5
error('dummy');
end
catch err
disp('catch')
continue;
end
metr{ix} = 1;
end
当第100次迭代未写入结果(metr{ix} = 1
)时,会出现问题。我只能建议不要在parfor循环中使用continue
。在任何情况下都应该用if
替换。
答案 1 :(得分:0)
相当古老的问题,但为了以防万一,我不认为原始代码中的逻辑是正确的。我会避免使用continue
语句,因为parfor的主体是在每个工作节点中独立执行的。对于工人来说,在这种情况下没有循环的概念,因此,现在没有任何东西可以继续。假设代码没有崩溃,parfor将继续迭代中的下一个元素。我对原始代码的看法是
% Initialise empty cell array
metr = cell(1,length(paths));
% Iterate over the elements in parallel
parfor i = 1:length(paths)
try
% Try to execute the below
a = read(path{i});
errB = 0;
catch ME
% Suppress the exception - parfor loop now continues
errB = 1;
end
% Execute dosomething()
if ~errB
metr{i} = dosomething(a);
end
end
更好的选择可能是
% Initialise empty cell array
metr = cell(1,length(paths));
% Iterate over the elements in parallel
parfor i = 1:length(paths)
try
% Try to execute the below
metr{i} = dosomething(read(path{i}));
catch ME
% Suppress the exception - parfor loop now continues
% NOTE: metr{i} is empty for this i.
end
end
不确定是否有metr
作为列的原因,但由于Matlab按列主要顺序运行,因此感觉更自然地做metr = cell(length(paths),1)
。