簡體   English   中英

通過 Openmp 任務訪問實例變量(隱式 firstprivate)時出現分段錯誤

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

這個問題特定於 OpenMP 3.0 中的任務構造及其對 C++ 的隱式 firstprivate 的使用。 我正在尋找問題的解釋以及可能的解決方案。

我正在處理的程序有一些分段錯誤; 我設法將問題減少到以下測試用例。

出現問題是因為我正在從#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;
}

當我使用 gcc 4.5 或更高版本(支持 OpenMP 中的任務功能的版本)(即gcc -fopenmp myprogram.cpp )編譯和運行程序時,它運行良好。 但是當我使用英特爾的 C++ 編譯器(也支持任務功能的版本)編譯和運行程序時,即icpc -openmp myprogram.cpp它出現了段錯誤。

GCC 的 output:

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

ICPC的output:

Segmentation fault

我假設其中至少有一個是錯誤的。 我的具體問題:

  1. 是什么導致了問題? 是因為我在#pragma omp task中使用了someInstanceVariable並且它導致了對 this 指針的隱式 firstprivate 引用嗎?
  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; } } }

有沒有其他方法不創建臨時變量?

這是 OpenMP 的痛苦問題之一。 由於 OpenMP 不是基本語言 (C/C++) 的一部分,因此 OpenMP 難以處理 class 對象。 原因是 object 在 OpenMP“附加組件”看到 object 時可能未實例化。 在某些情況下可以做到這一點,但到目前為止,OpenMP 規范已經決定最好不要嘗試處理對象的任何情況。 這就是為什么,如果您閱讀 OpenMP 規范,它指的是變量。 變量在基礎語言中有一個非常具體的定義。

Firstprivate 處理變量而不是 class 對象。 英特爾編譯器不會使 class object 成為第一個私有的,因此當您嘗試打印 someInstanceVaribale 的值時,大多數情況下您會遇到段錯誤(因為它的地址為零,因為它是共享的並且已經消失超出范圍)。 似乎 g++ 所做的比 OpenMP 規范所要求的要多。 在任何情況下,如果您創建指向 class object 的指針,則該指針可以設為 firstprivate,並將從任務中指向正確的 object。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM