Avoid race conditions when using parfor in MATLAB

I loop in parallel and change the variable if the condition is met. Super idiomatic code that I'm sure everyone has written a hundred times:

trials = 100;
greatest_so_far = 0;
best_result = 0;

for trial_i = 1:trials
    [amount, result] = do_work();

    if amount > greatest_so_far
        greatest_so_far = amount;
        best_result = result;
    end
end

      

If I wanted to replace for

with parfor

, how can I ensure that race conditions are not checked, should we replace greatest_so_far

? Is there a way to block this variable outside of validation? Perhaps for example:

trials = 100;
greatest_so_far = 0;
best_result = 0;

parfor trial_i = 1:trials
    [amount, result] = do_work();

    somehow_lock(greatest_so_far);
    if amount > greatest_so_far
        greatest_so_far = amount;
        best_result = result;
    end
    somehow_unlock(greatest_so_far);
end

      

+3


source to share


3 answers


Skewed answer. It doesn't exactly solve your problem, but it might help you avoid it.

If you can let memory store the outputs of yours do_work()

in some vectors, then you can just run yours in parfor

that function alone, store the result, and then hammer the result at the end (outside of the loop):

amount = zeros( trials , 1 ) ;
result = zeros( trials , 1 ) ;

parfor trial_i = 1:trials
    [amount(i), result(i)] = do_work();
end

[ greatest_of_all , greatest_index ] = max(amount) ;
best_result = result(greatest_index) ;

      




Edit / Comment : (I would like to put this in a comment on your question, but it was too long, sorry).
I am familiar with .net

and fully understand your lock / unlock request. I myself have tried many attempts to implement some sort of progress bar for a very long loop parfor

... to no avail.

If I understand Matlab's classification of the variable correctly , the fact that you assign greatest_so_far

(to greatest_so_far=amount

) makes Matlab treat this temporary variable, which will be cleared and reinitialized at the beginning of each iteration of the loop (therefore unsuitable for your purpose).

Thus, a simple locked variable may not be a concept that we can simply implement for now. Some confusing class event or file writing / checking might do the trick, but I'm afraid the time will suffer a lot. If each iteration takes a long time, the overhead may be worth it, but if you are using a parfoor

lot of short execution iterations to speed up, then confusing solutions will slow you down more than they help ...

You can take a look at this stack exchange question, you might find something interesting for your case: Semaphores and Locks in MATLAB

+2


source


Solution from Hoki is the correct way to solve the problem as stated. However, when you asked about race conditions and prevented them when loop iterations depend on each other, you may need to look into the spmd

various functions as welllab*

.



+2


source


To do this you need to use SPMD - SPMD allows communication between workers. Something like that:

bestResult = -Inf;
bestIndex  = NaN;
N = 97;
spmd
  % we need to round up the loop range to ensure that each
  % worker executes the same number of iterations
  loopRange = numlabs * ceil(N / numlabs);
  for idx = 1:numlabs:loopRange
    if idx <= N
      local_result = rand(); % obviously replace this with your actual function
    else
      local_result = -Inf;
    end
    % Work out which index has the best result - use a really simple approach
    % by concatenating all the results this time from each worker
    % allResultsThisTime will be 2-by-numlabs where the first row is all the
    % the results this time, and the second row is all the values of idx from this time
    allResultsThisTime = gcat([local_result; idx]);
    % The best result this time - consider the first row
    [bestResultThisTime, labOfBestResult] = max(allResultsThisTime(1, :));
    if bestResultThisTime > bestResult
      bestResult = bestResultThisTime;
      bestIndex  = allResultsThisTime(2, labOfBestResult);
    end
  end
end
disp(bestResult{1})
disp(bestIndex{1})

      

+1


source







All Articles