parfor loop with continue gives incorrect results
이전 댓글 표시
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
Matt J
2018년 10월 8일
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
2018년 10월 9일
Statistically approximately 300 would be most common.
Question: have you tried nnz() to cross check sum()?
Steve Chang
2018년 10월 9일
답변 (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
Steve Chang
2018년 10월 9일
Matt J
2018년 10월 9일
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
2018년 10월 9일
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
2018년 10월 9일
Walter Roberson
2018년 10월 10일
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
2018년 10월 10일
Edric Ellis
2018년 10월 11일
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
2018년 10월 11일
카테고리
도움말 센터 및 File Exchange에서 Startup and Shutdown에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!