【问题标题】:Continue in parfor loop继续 parfor 循环
【发布时间】:2015-03-06 14:54:43
【问题描述】:

我在 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 的错误而崩溃。

但是,如果我将其重写如下,我不会收到任何错误并且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 语句之后继续执行。我认为只有 break; 在 parfor 循环中不受支持,而 continue 有效。 我很困惑……

附言错误:

'metr' 的工作人员引发了 UndefinedFunction 错误。
这可能是因为文件包含 'metr' 工人无法访问。

编辑:好的,我找到了谁的错。似乎如果我从catch err 行中删除err 变量,它会突然正常工作!我仍然不知道为什么将错误分配给变量会使循环变得疯狂。

【问题讨论】:

  • 你确认结果是一样的吗?
  • 是的,我查过了,他们是

标签: matlab parfor


【解决方案1】:

我仔细查看了您的代码。我无法准确重现您的错误,但并行计算工具箱存在问题并继续。在 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

【讨论】:

    【解决方案2】:

    相当老的问题,但以防万一,我认为原始代码中的逻辑不正确。我会避免使用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) 感觉更自然一些。

    【讨论】:

      猜你喜欢
      • 2011-08-19
      • 1970-01-01
      • 2014-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多