1

I'm working with OpenMP in C++ and try to make a static member variable of a class threadprivate. A very simplified example code example looks like this

#include <omp.h>
#include<iostream>

template<class numtype>
class A {
public:
    static numtype a;
    #pragma omp threadprivate(a)
};

template<class numtype>
numtype A<numtype>::a=1;

int main() {

 #pragma omp parallel
 {

  A<int>::a = omp_get_thread_num();

  #pragma omp critical
  {
    std::cout << A<int>::a << std::endl;
  }
 } /* end of parallel region */    
}

If I try to compile this code with the gcc compiler I get the error message

threadprivatetest.cpp:8:27: error: ‘a’ has not been declared

#pragma omp threadprivate(a)

The code compiles and runs if I use the Intel C++ compiler. When I searched for the error I already found that some answers to this problem.

Using the OpenMP threadprivate directive on static instances of C++ STL types

However since this is for a larger project to where I want to use the gcc compiler and since the linked post is already 6 years old. Is there a possibility do compile such code with the gcc compiler today? Could somebody explain the work around mentioned in the old post in detail, because i wasn't able to understand it?

Thanks for your help!

  • Hmm. You can imagine a template rather as macro than as ready code. Thus, the problem is probably that the `#pragma omp threadprivate(a)` fails as `a` hasn't "real existence" until the template is instanced. Did you try move the `#pragma omp threadprivate(a)` to the line after `A::a = omp_get_thread_num();`. Alternatively, you could instance your template explicitly (for type `int`) and move `#pragma omp threadprivate(a)` after this. Probably you have to apply some scope to `a` in this case. (Please, consider that I don't know anything about OMP. I was just loud thinking about options.) – Scheff's Cat Nov 24 '17 at 16:19
  • Just had a look onto the link you provided. The difference to your code is really, that the linked sample code applies `#pragma omp` to instances of (templated) classes. (They have storage.) You instead try to apply the `#pragma omp` to a member of a class template. (It has not (yet) storage (until template is instanced).) I could imagine that the former is no problem but the latter beyond of that what OMP is capable. – Scheff's Cat Nov 24 '17 at 16:27
  • I have recently looked up this problem again. You were probably right back then, that this is beyond the scope of what OMP is capable of. However it seems, that making the member variable a pointer to the object solves this problem. – Thomas Dick Feb 16 '18 at 14:29
  • I didn't understand your last sentence "However it seems, that making the member variable a pointer to the object solves this problem." Could you [edit] your question and add your new sample (which seems to work)? (Please, don't change existing text too much beyond fixing little typos.) If you found an answer by yourself then you are welcome to post it: [SO: Can I answer my own question?](https://stackoverflow.com/help/self-answer) – Scheff's Cat Feb 16 '18 at 14:49

1 Answers1

2

The following code works and does what I originally intended to do.

#include <omp.h>
#include<iostream>

template<class numtype>
class A {
public:
  static numtype* a;
  #pragma omp threadprivate(a)
};

template<class numtype>
numtype* A<numtype>::a=nullptr;

template class A<int>;

int main() {
  #pragma omp parallel
  {

    A<int>::a = new int;
    *A<int>::a = omp_get_thread_num();

    #pragma omp critical
    {
      std::cout << *A<int>::a << std::endl;
    }
  } /* end of parallel region */
}

As you can see the difference is that a is now a pointer to numtype instead of numtype.