Class declaring itself (*this) private to avoid race conditions / quest for threadprivate in gcc abandoned

This is a long-standing missing GCC feature:

  • OpenMP threadprivate directive does not work with non-POD types

With current GCC versions, thread_local is expected to work, though:

int main() {
  thread_local lotswork production(0);
  production.carryout();
}

However, I do not think this will work in your case because the parallel loop in carryout will still operate on a single lotswork instance. I believe this would apply to the original code using threadprivate, too. You probably need to move the parallel loop outside of the carryout member function.


It seems like there is some confusion about OpenMP constructs here. threadprivate is used, much like thread_local, to create a per-thread copy of an object of static lifetime, either a global or a static variable. As noted, there are some implementation issues with this, but even if the implementations could handle the class, using threadprivate on a non-static local variable would produce an error.

As to the error, it's hard to say without output, but it is likely multiple things:

  1. The unmatched closing brace. Placing a { on the end of a pragma line does not open a block, it needs to be on the following line.
  2. It is not valid to privatize an enclosing class instance that way

If you need to create a private copy of the enclosing class in each thread, it's possible by either copy-constructing the class into a variable declared inside a parallel region:

#pragma omp parallel
{
  lotswork tmp(*this);
  // do things with private version
}

Note however that the entire thing is private, so this means that f in the original copy will not be updated unless you perform the addInt equivalents all on the private copies then the f[n] assignments on the original.

Edit: I originally mentioned using the default(firstprivate) clause, but the default clause only offers private and first private for FORTRAN. To get the same effect in c++, do the above and copy construct into a new instance of each, or use a lambda with capture by value by default then firstprivate that, *this requires c++17 to work, but does exactly what's requested:

auto fn = [=,*this](){
  // do things with private copies
  // all updates to persist in shared state through pointers
};
#pragma omp parallel firstprivate(fn)
fn();

Tags:

C++

Gcc

Openmp