简体   繁体   English

通过 Openmp 任务访问实例变量(隐式 firstprivate)时出现分段错误

[英]Segmentation fault when accessing a instance variable (implicit firstprivate) through Openmp task

This question is specific to the task construct in OpenMP 3.0 and its use of implicit firstprivate for C++.这个问题特定于 OpenMP 3.0 中的任务构造及其对 C++ 的隐式 firstprivate 的使用。 I am looking for an explanation of the problem and also possible solutions.我正在寻找问题的解释以及可能的解决方案。

I had some segmentation fault with a program that I was working on;我正在处理的程序有一些分段错误; I managed to reduce the problem to the following test case.我设法将问题减少到以下测试用例。

The problem occurs because I am accessing an instance variable (of object A) from within a #pragma omp task出现问题是因为我正在从#pragma omp task中访问实例变量(object A)

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

using namespace std;

class A {
private:
  int someInstanceVariable;

public:
    // This is never called
  A(int _someInstanceVariable) {
    someInstanceVariable = _someInstanceVariable;
  }

  A(const A& _A) {
    cout << "Copy constructor called" << endl;
    someInstanceVariable = _A.someInstanceVariable;
  }

  void simpleTask() {
    // This task makes a reference to someInstanceVariable in the current object
    #pragma omp task
    { 
      // For access to stdout
      #pragma omp critical
      {
        // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        // This line uses someInstanceVariable and causes a segfault
        // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        cout << "The value of the someInstanceVariable = " << someInstanceVariable << endl;
      }
    }
  }
};

int main(int argc, char* argv[]) {

  #pragma omp parallel
  {
    #pragma omp single
    {
      for(int i = 0; i < 10; i++) {
        A* temp = new A(i);
        temp->simpleTask();
      }
    }
  }

  return 0;
}

When I compile and run the program with gcc 4.5 or higher (the version that supports the task feature in OpenMP) ie gcc -fopenmp myprogram.cpp it runs fine.当我使用 gcc 4.5 或更高版本(支持 OpenMP 中的任务功能的版本)(即gcc -fopenmp myprogram.cpp )编译和运行程序时,它运行良好。 But when I compile and run the program with Intel's C++ compiler (the version that also supports the task feature) ie icpc -openmp myprogram.cpp it segfaults.但是当我使用英特尔的 C++ 编译器(也支持任务功能的版本)编译和运行程序时,即icpc -openmp myprogram.cpp它出现了段错误。

GCC's output: GCC 的 output:

The value of the someInstanceVariable = 0
The value of the someInstanceVariable = 1
...

ICPC's output: ICPC的output:

Segmentation fault

I am assuming that at least one of them must be wrong.我假设其中至少有一个是错误的。 My specific questions:我的具体问题:

  1. What is causing the problem?是什么导致了问题? Is it because I am using someInstanceVariable in the #pragma omp task and it is causing an implicit firstprivate reference to the this pointer?是因为我在#pragma omp task中使用了someInstanceVariable并且它导致了对 this 指针的隐式 firstprivate 引用吗?
  2. Even better, could someone point me to the specific section in the OpenMP 3.0 spec that talks about this?更好的是,有人能指出我在OpenMP 3.0 规范中讨论这个的特定部分吗?
  3. I know that I can fix the problem by creating an local variable我知道我可以通过创建局部变量来解决问题

    void simpleTask() { // This task makes a reference to someInstanceVariable in the current object #pragma omp task { int tempVariable = this -> someInstanceVariable; // For access to stdout #pragma omp critical { cout << "The value of the someInstanceVariable = " << tempVariable << endl; } } }

Are there other ways without creating a temp variable?有没有其他方法不创建临时变量?

This is one of the painful problems with OpenMP.这是 OpenMP 的痛苦问题之一。 Since OpenMP is not part of the base langauge (C/C++), it is difficult for OpenMP to handle class objects.由于 OpenMP 不是基本语言 (C/C++) 的一部分,因此 OpenMP 难以处理 class 对象。 The reason, is that the object may not be instantiated at the time the OpenMP "add-on" sees the object.原因是 object 在 OpenMP“附加组件”看到 object 时可能未实例化。 There are cases where it could be done, but up to now the OpenMP specification has decided it better not to try and handle any of the cases for objects.在某些情况下可以做到这一点,但到目前为止,OpenMP 规范已经决定最好不要尝试处理对象的任何情况。 That is why, if you read the OpenMP specification it refers to variables.这就是为什么,如果您阅读 OpenMP 规范,它指的是变量。 Variables have a very specific definition in the base languages.变量在基础语言中有一个非常具体的定义。

Firstprivate deals with variables and not class objects. Firstprivate 处理变量而不是 class 对象。 The Intel compiler doesn't make the class object firstprivate, so when you try and print the value of someInstanceVaribale you are going to get a segment fault most of the time (because it has an address of zero, since it is shared and has gone out of scope).英特尔编译器不会使 class object 成为第一个私有的,因此当您尝试打印 someInstanceVaribale 的值时,大多数情况下您会遇到段错误(因为它的地址为零,因为它是共享的并且已经消失超出范围)。 It seems as though g++ has done more than what the OpenMP specification calls for.似乎 g++ 所做的比 OpenMP 规范所要求的要多。 In any case, if you make a pointer to the class object, that pointer can be made firstprivate and will point to the correct object from within the task.在任何情况下,如果您创建指向 class object 的指针,则该指针可以设为 firstprivate,并将从任务中指向正确的 object。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM