Continue in parfor loop

2019-08-29 06:06发布

I have a kind of weird error in 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

The above code works fine as a normal loop and catches two errors and continues. If I make it a parfor loop, the moment it catches an error it goes totally crazy running the for loop again from the beginning and at the end crashing with an error of not finding the variable metr.

However, if I rewrite it as follows I don't get any error and the parfor loop works, whether or not I leave the continue statement:

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

Does anyone understand what is going on? It seems like it keeps executing after the continue statement. I thought only break; was not supported in parfor loops and that continue worked. I'm very confused...

p.s. the error:

An UndefinedFunction error was thrown on the workers for 'metr'.
This may be because the file containing 'metr' is not accessible on the workers.

Edit: Okay I found who's at fault. It seems that if I remove the err variable from the catch err line it suddenly works correctly! I still have no clue why assigning the error to a variable makes the loop go crazy.

标签: matlab parfor
2条回答
再贱就再见
2楼-- · 2019-08-29 06:45

I took a closer look at your code. I was not able to reproduce exactly your error, but there is a problem with the parallel computing toolbox and continue. In Matlab 2013a the following lines crash with a probability of 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

The problem occurs when the 100th iteration is not writing the result (metr{ix} = 1). I can only give the recommendation not to use continue in a parfor loop. It should be replaceable with if in any case.

查看更多
迷人小祖宗
3楼-- · 2019-08-29 07:08

Rather old question but just in case, I don't think the logic in the original code is correct. I would avoid using the continue statement since the body of the parfor is executed in every worker node independently. For the worker there is no concept of a loop in this case and therefore as it stands there is nothing to continue to. parfor will continue to the next element in the iteration assuming the code hasn't crashed. My take on the original code would be

% 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

An even better take could be

% 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

Not sure if there is a reason for having metr as columns but since Matlab operates in column-major order it feels a bit more natural to do metr = cell(length(paths),1) instead.

查看更多
登录 后发表回答