2011-06-30 13 views
5

この質問は、OpenMP 3.0のタスク構造とC++の暗黙的なfirstprivateの使用に固有です。私は問題の説明と可能な解決策を探しています。OpenMPタスクによるインスタンス変数(暗黙のfirstprivate)にアクセスする際のセグメンテーションフォルト

私が取り組んでいるプログラムでは、いくつかのセグメンテーション違反がありました。私は次のテストケースに問題を減らすことができました。私はインスタンス変数にアクセスしていますので、私はGCC 4.5以降でプログラムをコンパイルして実行すると

問題は、タスク機能をサポートするバージョン(#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; 
} 

内から(オブジェクトAの)発生しますOpenMPで)gcc -fopenmp myprogram.cppそれは正常に動作します。しかし、私がコンパイルして、インテルのC++コンパイラ(タスク機能もサポートしているバージョン)でプログラムを実行すると、icpc -openmp myprogram.cppというセグメンテーションが発生します。

GCCの出力:

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

ICPCの出力:

Segmentation fault 

私はそれらの少なくとも1つが間違ってなければならないことを想定しています。私の具体的な質問:

  1. 何が原因ですか?それは#pragma omp tasksomeInstanceVariableを使用していて、このポインタへの暗黙的な第1のプライベート参照を引き起こしているからですか?
  2. これについて語るOpenMP 3.0 specの特定のセクションに誰かが指摘できますか?私は、ローカル変数に

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

を作成することで問題を解決できることを知っている

  • は、一時変数を作成することなく、そこに他の方法はありますか?

  • 答えて

    2

    これはOpenMPの厄介な問題の1つです。 OpenMPは基本言語(C/C++)の一部ではないため、OpenMPがクラスオブジェクトを処理することは困難です。その理由は、OpenMPの "アドオン"がオブジェクトを認識した時点でオブジェクトがインスタンス化されない可能性があるからです。それが可能な場合がありますが、これまでOpenMP仕様では、オブジェクトのケースを処理しない方が良いと判断しました。そのため、OpenMP仕様を読んだ場合は、変数を参照します。変数は基本言語で非常に明確な定義を持っています。

    Firstprivateはクラスオブジェクトではなく変数を扱います。インテル®コンパイラーはクラスオブジェクトを最初に作成しません。したがって、someInstanceVaribaleの値を試して印刷すると、ほとんどの場合セグメント違反が発生します(アドレスが共有され、範囲外)。あたかもg ++がOpenMP仕様が要求する以上に多くのことを行ったようです。いずれにしても、クラスオブジェクトへのポインタを作成すると、そのポインタを最初にプライベートにでき、タスク内から正しいオブジェクトを指し示すことができます。

    +0

    「変数」という用語の定義を指定する関連セクションを指摘できますか?クラスオブジェクトの説明に最も近いのは、93ページのセクション2.9.3.4です。「構造体の配列としての別の変数の一部である変数はfirstprivate節に現れません」と書かれています。しかし、私はfirstprivate句で何も明示的に指定しなかったので、コンパイラは自動的にリファレンスを作成しました(誤っているように見えますが)。なぜコンパイラは処理するのではなく、エラーを通知するだけでしたか?私が誤解している何か他のものがありますか? – vazexqi

    +0

    @vazexqi私は現在、同様の問題を扱っています。この問題にあなたの説明/解決策を教えてください。 OpenMPでクラスオブジェクトを処理する方法は私にはまだ分かりません。 – Callahan

    関連する問題