Ошибка сегментации при доступе к переменной экземпляра (неявный firstprivate) через задачу Openmp - PullRequest
6 голосов
/ 30 июня 2011

Этот вопрос относится к конструкции задачи в OpenMP 3.0 и ее использованию неявного firstprivate для C ++. Я ищу объяснение проблемы, а также возможные решения.

У меня была ошибка сегментации с программой, над которой я работал; Мне удалось свести проблему к следующему контрольному примеру.

Проблема возникает из-за того, что я обращаюсь к переменной экземпляра (объекта 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;
}

Когда я компилирую и запускаю программу с gcc 4.5 или выше (версия, которая поддерживает функцию задачи в OpenMP), т.е. gcc -fopenmp myprogram.cpp, она работает нормально. Но когда я компилирую и запускаю программу с помощью компилятора Intel C ++ (версия, которая также поддерживает функцию задачи), то есть icpc -openmp myprogram.cpp, она вызывает ошибки.

Выход GCC:

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

Вывод ICPC:

Segmentation fault

Я предполагаю, что хотя бы один из них должен быть не прав. Мои конкретные вопросы:

  1. В чем причина проблемы? Это потому, что я использую someInstanceVariable в #pragma omp task, и это вызывает неявную первоприватную ссылку на указатель this?
  2. Еще лучше, может кто-нибудь указать мне на конкретный раздел в спецификации OpenMP 3.0 , который говорит об этом?
  3. Я знаю, что могу решить проблему, создав локальную переменную

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

Есть ли другие способы без создания временной переменной?

1 Ответ

3 голосов
/ 30 июня 2011

Это одна из болезненных проблем с OpenMP.Поскольку OpenMP не является частью базового языка (C / C ++), OpenMP трудно обрабатывать объекты классов.Причина в том, что объект не может быть создан в тот момент, когда «надстройка» OpenMP видит объект.Есть случаи, когда это можно было бы сделать, но до сих пор спецификация OpenMP решила, что лучше не пытаться обрабатывать какие-либо случаи для объектов.Вот почему, если вы читаете спецификацию OpenMP, это относится к переменным.Переменные имеют очень конкретное определение в базовых языках.

Firstprivate имеет дело с переменными, а не с объектами классов.Компилятор Intel не делает объект класса firstprivate, поэтому, когда вы попытаетесь напечатать значение someInstanceVaribale, большую часть времени вы получите ошибку сегмента (потому что он имеет нулевой адрес, так как он является общим и уже существуетвыходит за рамки).Кажется, что g ++ сделал больше, чем требует спецификация OpenMP.В любом случае, если вы сделаете указатель на объект класса, этот указатель может быть сделан первым и будет указывать на правильный объект изнутри задачи.

...