Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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++. 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

#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) i.e. gcc -fopenmp myprogram.cpp it runs fine. But when I compile and run the program with Intel's C++ compiler (the version that also supports the task feature) i.e. icpc -openmp myprogram.cpp it segfaults.

GCC's output:

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

ICPC's 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?
  2. Even better, could someone point me to the specific section in the OpenMP 3.0 spec that talks about this?
  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?

like image 373
vazexqi Avatar asked Jun 30 '11 15:06

vazexqi


1 Answers

This is one of the painful problems with OpenMP. Since OpenMP is not part of the base langauge (C/C++), it is difficult for OpenMP to handle class objects. The reason, is that the object may not be instantiated at the time the OpenMP "add-on" sees the 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. That is why, if you read the OpenMP specification it refers to variables. Variables have a very specific definition in the base languages.

Firstprivate deals with variables and not class objects. 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). It seems as though g++ has done more than what the OpenMP specification calls for. 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.

like image 174
ejd Avatar answered Sep 27 '22 16:09

ejd