Thinking Parallel

A Blog on Parallel Programming and Concurrency by Michael Suess

Breaking Out of Loops in OpenMP

A Coaster LoopI have been quite late with my post this week, I apologize for that, but I have been sick with a cold (and I still am). Couple that with the fact that I did not find the time to write one or two posts in advance since Iwomp and you see why I am late this week. Hope my sickness does not influence my writing style too badly :grin:. Anyways. From time to time, readers write me their problems related to parallel programming. Especially with C++ and OpenMP. And while omp@openmp.org is probably the better place to ask those questions, I still try to help as much as I can and as much as my time permits, at least if its an interesting problem. The problem I would like to talk about today falls into this category for me, as it requires an interesting workaround: its the problem of how to throw an exception out of a parallel loop in OpenMP. Can’t do that, I hear you say? If you have read my past articles about exceptions and OpenMP you know that it is not trivial. But its doable with a little trick.

The code snippet my reader presented me with looked like this:

  1. int n(0);
  2.  
  3. #pragma omp parallel for
  4. for (int i = 0; i < 1000; ++i) {
  5.  
  6.     // Update progress
  7.     if (pCall->Aborted) {
  8.         throw abort_exception;
  9.     }
  10.    
  11.     #pragma omp critical(UpdateProgress)
  12.         pCall->Notify("Progress...", n * 100 / 1000);
  13.  
  14.     // Do something....
  15.        
  16.     #pragma omp critical(UpdateProgress)
  17.         ++n;
  18. } // end for

If the call to pCall->Aborted returns true, the user has canceled the current computation and every thread should stop working. Actually, we have not one problem here, but two:

  • We are not allowed to cancel work in a parallel region. I have had this problem so many times in the past that I have even worked on a proposal to solve it for my PhD. There is a publication available if you are interested in my solution. However, since it is quite big, requires changes in the compilers and I know you are not here to read my papers, I will show you the (much shorter) workaround instead.
  • We are not allowed to throw an exception out of a parallel region.

If you like to solve problems like this yourself, now is the time to stop reading and go craft a solution :grin:.

Got it? Since the workaround is not that complicated, I will restrain myself from keeping you away from it any longer, here it is:

  1. int n(0);
  2. bool abort = false;
  3.  
  4. #pragma omp parallel for
  5. for ( i=0; i<1000; ++i )
  6. {
  7.     #pragma omp flush (abort)
  8.     if (!abort) {
  9.  
  10.         //Update progress
  11.         if ( pCall->Aborted ) {
  12.             abort = true;
  13.             #pragma omp flush (abort)
  14.         }
  15.  
  16.         #pragma omp critical(UpdateProgress)
  17.         pCall->Notify("Progress...", n*100/1000);
  18.  
  19.         //Do something....
  20.  
  21.         #pragma omp critical(UpdateProgress)
  22.         ++n;
  23.     }
  24. }
  25.  
  26. if (abort)
  27. {
  28.     throw abort_exception;
  29. }

As you can see, the exception is no longer thrown from inside the parallel region, therefore the code is conforming OpenMP now. We also cannot break out of the for-loop directly, as the OpenMP-specification requires every loop iteration to be carried out. But using the branch on the abort-variable, we can make sure that as soon the user aborts the calculation, no useful work is being done anymore, therefore the calculation will finish really fast afterwards.

The last thing to mention here is the use of the explicit flush, which I usually don’t do anymore, because it is so error-prone. The use-case shown here (updating a boolean variable) is actually the only safe and portable way to use the explicit flush – a sad fact about OpenMP that warrants its own post (I have been meaning to post about the memory model for a looong time).

Hope you had some fun with todays episode of “find the workaround” :smile:!

10 Responses to Breaking Out of Loops in OpenMP


Comments