parfor loop with continue gives incorrect results
Mostrar comentarios más antiguos
Consider the following code:
N = 1000;
failed = false( 1, N );
values = cell( 1, N );
n_failed = 0;
parfor idx = 1:N
try
if ( rand() > 0.7 )
n_failed = n_failed + 1;
error( '' );
end
catch err
failed(idx) = true;
continue;
end
values{idx} = rand( 1e3, 1 );
end
fprintf( 'N failed 1: %d\n\n', sum(failed) );
fprintf( 'N failed 2: %d\n', n_failed );
If I run this on my machine (macOS 10.12, r2017a), `sum(failed)` is 0, while `n_failed` is, as expected, ~300. What am I missing here? I don't see anything in the documentation about `continue` not being supported in a parfor loop?
4 comentarios
Matt J
el 8 de Oct. de 2018
while `n_failed` is, as expected, ~300
How can you have any expectations at all about sum(failed) or n_failed, when their values are driven by the randomization in
if ( rand() > 0.7 )
Walter Roberson
el 9 de Oct. de 2018
Statistically approximately 300 would be most common.
Question: have you tried nnz() to cross check sum()?
Steve Chang
el 9 de Oct. de 2018
Respuestas (1)
Don't pass an empty string '' to error() if you want the catch block to be triggered. An empty string apparently does not result in an error being thrown.
In other words, this works fine:
N = 1000;
failed = false( 1, N );
n_failed = 0;
parfor i = 1:N
try
if ( rand() > 0.7 )
n_failed = n_failed + 1;
error('an error');
end
catch
failed(i) = true;
continue
end
end
fprintf( 'N failed 1: %d\n\n', sum(failed) );
fprintf( 'N failed 2: %d\n', n_failed );
9 comentarios
Steve Chang
el 9 de Oct. de 2018
Matt J
el 9 de Oct. de 2018
Bizarre. Well, I don't understand the problem, but I do find that removing the continue fixes it. I also find that moving the assignment to values up several lines also fixes it:
N = 1000;
failed = false( 1, N );
values = cell( 1, N );
n_failed = 0;
parfor idx = 1:N
values{idx} = rand( 1e3, 1 );
try
if ( rand() > 0.7 )
n_failed = n_failed + 1;
error( 'A' );
end
catch err
failed(idx) = true;
continue;
end
end
fprintf( 'N failed 1: %d\n\n', sum(failed) );
fprintf( 'N failed 2: %d\n', n_failed );
Steven Lord
el 9 de Oct. de 2018
Don't pass an empty string '' to error() if you want the catch block to be triggered. An empty string apparently does not result in an error being thrown.
That is correct. The last item in the Tips section on the documentation page for the error function states that if all the inputs are empty, error does not throw an error.
Historically, error was often used with functions like nargchk that would return '' if the number of inputs was in the allowed range and an error message if not. Now, as the warning box at the top of the documentation page states, you should use narginchk (and/or nargoutchk) instead. Those will directly throw the error, so you don't need to wrap them in error calls.
The code above works, but I'm experiencing a different error with my original code.
That suggests that your original code is doing something different than the code you posted in Answers, and the differences between those two sections of code is relevant. Post your original code, or simplify the original code down to the minimal working example that reproduces the exact error you're seeing, and we may be able to offer guidance relevant to that original code.
That suggests that your original code is doing something different than the code you posted in Answers
@Steven Lord, The posted code does reproduce the problem, when a non-empty string is passed to error().
N = 1000;
failed = false( 1, N );
values = cell( 1, N );
n_failed = 0;
parfor idx = 1:N
try
if ( rand() > 0.7 )
n_failed = n_failed + 1;
error( 'A' );
end
catch err
failed(idx) = true;
continue;
end
values{idx} = rand( 1e3, 1 );
end
fprintf( 'N failed 1: %d\n\n', sum(failed) );
fprintf( 'N failed 2: %d\n', n_failed );
In R2018a, the above gives,
Error using test>(parfor consume)
Unable to perform assignment because the left and right sides have a different number
of elements.
Error in test (line 9)
parfor idx = 1:N
Steve Chang
el 9 de Oct. de 2018
Walter Roberson
el 10 de Oct. de 2018
continue is going to proceed to the next parfor iteration -- without having executed the assignment to values{i} that is after the continue.
Steve Chang
el 10 de Oct. de 2018
Edric Ellis
el 11 de Oct. de 2018
There's an existing problem in the parfor machinery that causes the values assignment to fail. The problem relates to the combination of try / catch and the assignment to values. You can trick the parfor machinery into operating correctly by changing how it analyses values. The following should work:
N = 1000;
failed = false( 1, N );
values = cell( 1, N );
n_failed = 0;
parfor idx = 1:N
% Dummy reference to "values(idx)":
if false
values(idx);
end
try
if ( rand() > 0.7 )
n_failed = n_failed + 1;
assert(false);
end
catch err
failed(idx) = true;
continue;
end
values{idx} = rand( 1e3, 1 );
end
fprintf( 'N failed 1: %d\n\n', sum(failed) );
fprintf( 'N failed 2: %d\n', n_failed );
Steve Chang
el 11 de Oct. de 2018
Categorías
Más información sobre Data Type Identification en Centro de ayuda y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!