2011-06-30 9 views
5

To pytanie dotyczy budowania zadań w OpenMP 3.0 i użycia domyślnej pierwszejprywatnej dla C++. Szukam wyjaśnienia problemu, a także możliwych rozwiązań.Błąd segmentacji podczas uzyskiwania dostępu do zmiennej instancji (niejawny firstprivate) do zadania OpenMP

Miałem pewne usterki segmentacji w programie, nad którym pracowałem; Udało mi się zredukować problem do następującego przypadku testowego.

Problem pojawia się, ponieważ mam dostępu do zmiennej instancji (obiektu a) od wewnątrz #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; 
} 

Kiedy skompilować i uruchomić program z gcc 4.5 lub wyższej (w wersji obsługującej funkcję zadania w OpenMP), tj. gcc -fopenmp myprogram.cpp działa poprawnie. Ale kiedy skompiluję i uruchomię program z kompilatorem C++ Intela (wersja, która obsługuje także funkcję zadania), tj. icpc -openmp myprogram.cpp, to ulega uszkodzeniu. Wyjście

GCC:

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

wyjście ICPC za:

Segmentation fault 

jestem przy założeniu, że co najmniej jeden z nich musi być źle. Moje szczegółowe pytania:

  1. Co powoduje problem? Czy to dlatego, że używam someInstanceVariable w #pragma omp task i powoduje to domyślne odniesienie do tego wskaźnika?
  2. Czy ktoś jeszcze może wskazać mi konkretną sekcję w OpenMP 3.0 spec, która mówi o tym?
  3. wiem, że mogę rozwiązać ten problem poprzez utworzenie zmiennej lokalnej

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

Czy istnieją inne sposoby, bez tworzenia zmiennej temp?

Odpowiedz

2

Jest to jeden z bolesnych problemów z OpenMP. Ponieważ OpenMP nie jest częścią języka podstawowego (C/C++), trudno jest OpenMP obsłużyć obiekty klasy. Powodem jest to, że obiekt nie może być utworzony w momencie, gdy "dodatek" OpenMP widzi obiekt. Są przypadki, w których można to zrobić, ale do tej pory specyfikacja OpenMP zdecydowała, że ​​lepiej nie próbować obsługiwać żadnych przypadków obiektów. Dlatego, jeśli czytasz specyfikację OpenMP, odnosi się ona do zmiennych. Zmienne mają bardzo szczegółową definicję w językach bazowych.

Firstprivate dotyczy zmiennych, a nie obiektów klasy. Kompilator Intela nie powoduje, że obiekt klasy jest pierwszym osobnym, więc gdy spróbujesz wydrukować wartość someInstanceVaribale, przez większość czasu otrzymasz błąd segmentu (ponieważ ma on zerowy adres, ponieważ jest udostępniony i zniknął poza zakresem). Wygląda na to, że g ++ zrobił więcej, niż wymaga tego specyfikacja OpenMP. W każdym przypadku, jeśli utworzysz wskaźnik do obiektu klasy, ten wskaźnik może zostać uczyniony pierwszorzędnym i wskaże prawidłowy obiekt z wewnątrz zadania.

+0

Czy możesz wskazać odpowiednią sekcję określającą definicję terminu "zmienne"? Najbliższe, jakie mogłem znaleźć w opisie obiektów klasowych, jest Sekcja 2.9.3.4 na stronie 93, gdzie jest napisane: "Zmienna, która jest częścią innej zmiennej (jako tablica struktury), nie może pojawić się w pierwszej klauzuli prywatnej".Jednakże, ponieważ nie sprecyzowałem niczego z klauzulą ​​firstprivate, kompilator automatycznie zadbał o dokonanie odwołania (choć wydaje się to niesłuszne). Dlaczego kompilator nie zasygnalizował błędu, zamiast kontynuować? Czy jest coś jeszcze, czego nie rozumiem? – vazexqi

+0

@vazexqi Obecnie mam podobny problem. Czy możesz podzielić się swoim wyjaśnieniem/rozwiązaniem tego problemu? Nie jest dla mnie jasne, jak postępować z obiektami klasowymi w OpenMP. – Callahan

Powiązane problemy