How to find out if inside an openMP parallel region?

c, c++, openmp

Solution

The OpenMP standard states that `omp_in_parallel()` returns true if and only if the enclosing `parallel` region is active. An active `parallel` region is defined to be one that is executed by a team consisting of more than one thread. In your case you have an inactive parallel region since there is one thread only. Thus `omp_in_parallel()` returns `false` and the `throw` is executed. It errs because the OpenMP standard restricts exceptions to the same parallel region and thread:

A `throw` executed inside a `parallel` region must cause execution to resume within the same `parallel` region, and the same thread that threw the exception must catch it.

This makes your code non-conformant since you let an exception pass unhandled through the parallel region. The same error is emitted by the Intel OpenMP run-time so it is not a GCC-specific behaviour.

What happens actually is that GCC transforms the OpenMP region by wrapping your code in a `try/catch` block with a catch-all exception filter:

#pragma omp parallel [child fn: main.omp_fn.0 (???)]
  {
    try
      {
        do_something ();
      }
    catch
      {
        <<<eh_filter (NULL)>>>
          {
            terminate ();
          }
      }
    #pragma omp return
  }

It is this catch-all exception filter that is responsibe for the termination message.

To resolve this the entire `try/catch` block should be inside the parallel region and not vice versa:

# pragma omp parallel
{
   try {
      do_something();
   } catch(int e) {
      std::cerr<<"error: '"<<e<<"'\n";  // never gets here
   }
}

(the additional block was added to make Intel C++ Compiler happy; it is not strictly necessary for GCC)

This outputs `error: '3'` as expected.

Edit: The funny thing is that your exception handler doesn't even make it into the final binary. Even given the default optimisation level of GCC (i.e. compiling with `g++ -fopenmp -o prog prog.cc`), the redundancy eliminator is able to detect that your exception handler would never be reached because of the implicit inner exception handler and thus your handler is removed. Then the compiler finds out that the implicit termination handler is also redundant, since there is already a top-level exception handler for the whole process that does the same (calls `terminate()`) and thus removes even the implicit one. The final code is so lean and mean - no exception handlers at all:

;; Function int main() (main, funcdef_no=970, decl_uid=20816, cgraph_uid=212)

int main() ()
{
  int e;
  int D.20855;
  struct basic_ostream & D.20854;
  struct basic_ostream & D.20853;
  void * D.20852;
  register int * D.20819;

<bb 2>:
  omp_set_num_threads (1);
  __builtin_GOMP_parallel_start (main._omp_fn.0, 0B, 0);
  main._omp_fn.0 (0B);
  __builtin_GOMP_parallel_end ();
  D.20855_1 = 0;
  // <------ See, ma', no exception handling at all :)

<L0>:
  return D.20855_1;

}

;; Function <built-in> (main._omp_fn.0, funcdef_no=976, decl_uid=20857, cgraph_uid=222)

<built-in> (void * .omp_data_i)
{
<bb 2>:
  do_something ();
  return;
  // <------ See, ma', they've nuked the implicit termination handler

}

One gets to love the `-fdump-tree-all` GCC option.

Edit: As to the question on how to fix `do_something()` - use `omp_get_level()` instead of `omp_in_parallel()`:

void do_something()
{
   if(omp_get_level() == 0)
     throw 3;
}

`omp_get_level()` returns the level of nesting of the `parallel` regions that enclose the call, no matter if they are active or not.

Problem

In my code, I want to avoid throwing exceptions from inside any openMP parallel region (because this results in an unhandled exception if not caught within the same region). To this end, I tried to use the openmp run-time library function ``` omp_in_parallel(); ``` to decide whether to throw an exception or write out an error message and terminate. However, under gcc 4.7.0 this will not work if there is only one thread to a parallel region: ``` #include <iostream> #include <omp.h> void do_something() { if(!omp_in_parallel()) // omp_in_parallel() returns false! throw 3; // so should be able to safely throw } int main() { omp_set_num_threads(1); try { # pragma omp parallel do_something(); } catch(int e) { std::cerr<<"error: '"<<e<<"'\n"; // never gets here } } ``` does not result in error: '3' but in terminate called after throwing an instance of 'int' Abort. Is this the correct behaviour (of `omp_in_parallel()`)? (the openMP standard appears sufficiently vague) or a bug in gcc? How can I fix the above code for `do_something()` so that it throws only when not in a parallel region?

Original source