Search code examples
c++structopenmpprivate

How to define a object or struct as threadprivate in OpenMP?


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;
        point2d(){
            x = 0;
            y = 0;
        }
        //copy constructor
        point2d(point2d& p){
            x = p.x;
            y = p.y;
        }
    };      

I declare a static structure and try to make them threadprivate

    static  point2d myPoint;
    #pragma omp threadprivate(myPoint)

It generates an error:

error C3057: 'myPoint' : dynamic initialization of 'threadprivate' symbols is not currently supported

Does it means that current openmp compiler doesn't support this to make a struct threadprivate? Or what I'm doing is wrong. Is there any alternate way to pass a struct or object?

Here's rest part of my codes:

    void myfunc(){
        printf("myPoint at %p\n",&myPoint);
    }

    void main(){
    #pragma omp parallel
       {
           printf("myPoint at %p\n",&myPoint);
           myfunc();
       }

    }

Solution

  • 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;
        }
    }