如何在OpenMP中定义一个对象或结构为线程私有

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

本文关键字:结构 线程 一个对象 OpenMP 定义      更新时间:2023-10-16

我不知道如何使结构体或对象作为threadprivate,我正在做的是产生一个错误:

    struct point2d{
        int x;
        int y;
        point2d(){
            x = 0;
            y = 0;
        }
        //copy constructor
        point2d(point2d& p){
            x = p.x;
            y = p.y;
        }
    };      

我声明了一个静态结构,并尝试将它们设为threadprivate

    static  point2d myPoint;
    #pragma omp threadprivate(myPoint)

生成错误:

错误C3057: 'myPoint': 'threadprivate'符号的动态初始化目前不支持

这是否意味着当前的openmp编译器不支持这使结构体threadprivate?或者我做的是错的。有没有其他方法来传递一个结构或对象?

下面是我代码的其余部分:

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

在c++中,带有方法的结构体是默认为public的class。它不是普通的旧数据(POD)。MSVC似乎暗示它可以处理线程私有对象(即非pod),但我似乎无法让它工作。我确实让它在GCC中工作,像这样:

extern point2d myPoint;
#pragma omp threadprivate(myPoint)
point2d myPoint;

但是有一个工作将与MSVC(以及GCC和ICC)一起工作。你可以使用线程私有指针。

threadprivate的目的是为每个线程提供对象/类型的私有版本,并使其值在并行区域之间保持持久。您可以这样做:删除指向point2d的指针,使该线程为私有,然后为并行区域中的每个线程分配私有指针的内存。请确保在最后一次并行调用时删除分配的内存。

#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 %dn", omp_get_thread_num(),myPoint->x, myPoint->y);
        }
    }   
    #pragma omp parallel
    {
        #pragma omp critical
        {
            printf("thread %d myPoint->x %d myPoint->y %dn", omp_get_thread_num(),myPoint->x, myPoint->y);
        }
        delete myPoint;
    }
}

您在代码中所做的是完全正确的。引用OpenMP标准(强调我的):

具有类类型的线程私有变量必须具有:

  • 一个可访问的,明确的默认构造函数,在没有给定初始化式的情况下;
  • 是一个可访问的、明确的构造函数直接初始化时的给定参数;
  • 一个可访问的,明确的复制构造函数,在使用显式初始化器进行复制初始化的情况下。

黑体字似乎正是你的情况。

您遇到的行为似乎是编译器中缺少的特性或错误。奇怪的是,即使GCC似乎也有问题,而英特尔声称工作得很好。