I don\'t know how to make a struct or object as threadprivate, what I\'m doing generates a error:
struct point2d{
int x;
int y;
p
What you do in your code is completely correct. Quoting the OpenMP standard (emphasis mine):
A threadprivate variable with class type must have:
- an accessible, unambiguous default constructor in case of default initialization without a given initializer;
- an accessible, unambiguous constructor accepting the given argument in case of direct initialization;
- an accessible, unambiguous copy constructor in case of copy initialization with an explicit initializer.
The one in bold seems exactly your case.
The behavior you encounter seems a missing feature or a bug in the compiler. Strangely enough, even GCC seems to have problem with that, while Intel is claimed to work fine.
In C++ a struct with methods is a Class where the default is public. It's not plain-old-data (POD). MSVC seems to imply that it can handle threadprivate objects (i.e. non-POD) but I can't seem to get it to work. I did get it working in GCC like this:
extern point2d myPoint;
#pragma omp threadprivate(myPoint)
point2d myPoint;
But there is a work around which will work with MSVC (as well as GCC and ICC). You can use threadprivate pointers.
The purpuse of threadprivate is to have private version of an object/type for each thread and have the values persistent between parallel regions. You can do that by delcaring a pointer to point2d
, making that threadprivate, and then allocating memory for the private pointer for each thread in a parallel region. Make sure you delete the allocated memory at your last parallel call.
#include <stdio.h>
#include <omp.h>
struct point2d {
int x;
int y;
point2d(){
x = 0;
y = 0;
}
//copy constructor
point2d(point2d& p){
x = p.x;
y = p.y;
}
};
static point2d *myPoint;
#pragma omp threadprivate(myPoint)
int main() {
#pragma omp parallel
{
myPoint = new point2d();
myPoint->x = omp_get_thread_num();
myPoint->y = omp_get_thread_num()*10;
#pragma omp critical
{
printf("thread %d myPoint->x %d myPoint->y %d\n", omp_get_thread_num(),myPoint->x, myPoint->y);
}
}
#pragma omp parallel
{
#pragma omp critical
{
printf("thread %d myPoint->x %d myPoint->y %d\n", omp_get_thread_num(),myPoint->x, myPoint->y);
}
delete myPoint;
}
}