2011-06-30 9 views
5

Esta pregunta es específica para la construcción de tareas en OpenMP 3.0 y su uso de firstprivate implícito para C++. Estoy buscando una explicación del problema y también posibles soluciones.Error de segmentación al acceder a una variable de instancia (firstprivate implícita) a través de la tarea de Openmp

Tuve algunos errores de segmentación con un programa en el que estaba trabajando; Logré reducir el problema al siguiente caso de prueba.

El problema se produce porque yo soy el acceso a una variable de instancia (de objeto A) desde dentro de un #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; 
} 

Cuando compilar y ejecutar el programa con gcc 4.5 o superior (la versión que soporta la función de tarea en OpenMP) es decir gcc -fopenmp myprogram.cpp funciona bien. Pero cuando compilo y ejecuto el programa con el compilador C++ de Intel (la versión que también admite la función de tarea), es decir, icpc -openmp myprogram.cpp, segmenta. salida

de GCC:

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

salida del CIPC:

Segmentation fault 

Estoy asumiendo que al menos uno de ellos debe estar equivocado. Mis preguntas específicas:

  1. ¿Cuál es la causa del problema? ¿Es porque estoy usando someInstanceVariable en el #pragma omp task y está causando una primera referencia implícita al este puntero?
  2. Mejor aún, ¿alguien podría indicarme la sección específica en el OpenMP 3.0 spec que habla de esto?
  3. sé que puedo solucionar el problema mediante la creación de una variable local

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

¿Hay otras maneras sin crear una variable temporal?

Respuesta

2

Este es uno de los dolorosos problemas con OpenMP. Como OpenMP no es parte del lenguaje base (C/C++), es difícil para OpenMP manejar objetos de clase. La razón es que el objeto no puede crearse una instancia en el momento en que el "add-on" de OpenMP ve el objeto. Hay casos en que podría hacerse, pero hasta ahora la especificación OpenMP ha decidido que es mejor no tratar y manejar ninguno de los casos para los objetos. Es por eso que, si lee la especificación OpenMP, se refiere a las variables. Las variables tienen una definición muy específica en los idiomas base.

Firstprivate trata con variables y no objetos de clase. El compilador de Intel no convierte el objeto de clase en primer privado, por lo que cuando intente imprimir el valor de alguna VariableVaribale obtendrá la mayor parte del tiempo un error de segmento (porque tiene una dirección de cero, ya que se comparte y se ha ido fuera del ámbito). Parece que g ++ ha hecho más de lo que exige la especificación OpenMP. En cualquier caso, si hace un puntero al objeto de la clase, ese puntero se puede hacer firstprivate y señalará el objeto correcto dentro de la tarea.

+0

¿Podría señalar la sección correspondiente que especifica la definición del término "variables"? Lo más parecido que pude encontrar a la descripción de objetos de clase es la Sección 2.9.3.4 en la página 93 donde dice "Una variable que es parte de otra variable (como una matriz de estructura) no puede aparecer en una cláusula firstprivate".Sin embargo, como no especifiqué explícitamente nada con una cláusula firstprivate, el compilador automáticamente se encargó de hacer una referencia (aunque erróneamente, parece). ¿Por qué el compilador simplemente no señalizó un error en lugar de proceder? ¿Hay algo más que estoy malentendiendo? – vazexqi

+0

@vazexqi Actualmente estoy lidiando con un problema similar. ¿Podría compartir su explicación/solución a este problema? Todavía no está claro cómo manejar objetos de clase en openMP. – Callahan

Cuestiones relacionadas