Search code examples
c++multithreadingopenmp

OpenMP: how to realize thread local object in task?


What I am trying to do is to iterate over all elements of a container in parallel comparable to #pragma omp for; however the container in question does not offer a random access iterator. I therefore use a workaround via tasks described in this stackoverflow answer:

for (std::map<A,B>::iterator it = my_map.begin();
        it != my_map.end();
        ++it)       
{
   #pragma omp task
   { /* do work with  it   */  }
}

My problem is that a 'scratch space' object is needed in each iteration; this object is expensive to construct or copy into the data environment of the task. It would only be necessary to have a single thread local object for each thread; in the sense that each task uses the object of the thread it is executed on. private requires a copy and shared results in a race condition. Is there a way to realize this with OpenMP?

I researched #pragma omp threadprivate, however the objects are not static, as the structure of the program looks something like this:

method(int argument_for_scratch_object){
   #pragma omp parallel
   {
      Object scratch(argument_for_scratch_object);

      //some computations are done here...
   
      #pragma omp single nowait
      {
         //here goes the for loop creating the tasks above
         //each task uses the scratch space object
      }
   }
}

If scratch was declared static (and then made threadprivate) before the parallel region, it would be initialized with argument_for_scratch_object of the first method call; which might not be correct for the subsequent method calls.


Solution

  • According to your update, I would suggest to use a global/static thread-private pointer and then initialize it by each thread within your parallel section.

    static Object* scratch_ptr;
    #pragma omp threadprivate(scratch_ptr);
    
    void method(int argument_for_scratch_object)
    {
    #pragma omp parallel
      {
        scratch_ptr = new Object(argument_for_scratch_object);
        ...
        delete scratch_ptr;  
      }
    }