2016-11-14 1 views
0

den Versuch, eine parallel zur Schleife zu schreiben, unter Verwendung von OpenMP V.2.0. In der Mitte der parallelen Region konstruiere ich ein Objekt, das ich einmal pro Faden konstruieren möchte.Execute Stück Code einmal pro Faden in OpenMP ohne Standardkonstruktors

#pragma omp parallel for 
    for (long i = 0; i < static_cast<long>(general_triangles.size()); ++i) 
    { 
     TrianglePointer tri = general_triangles[i]; 
     if (tri.GetClassification() == TO_CLASSIFY) 
     { 
      bool tri_has_correct_normal = true; 
      // --- Construct tree once per thread --- 
      Tree tree(*(gp_boolean_operator->mp_group_manager)); 
      if (tree.IsTriangleExternal(tri, tri_has_correct_normal)) 
      { 
       tri.SetClassification(IS_EXTERNAL); 
      } 
     } 
    } 

Gibt es ein Stichwort für die Konstruktion Baum einmal pro Thread?

Haben Sie vorschlagen, stattdessen verwenden bood_thread_ptr?

+0

Warum würden Sie werfen 'I' auf ein' long' statt nur einen 'std :: size_t' mit? – erip

+1

@erip, da size_t von openMP v.2.0 nicht unterstützt wird –

+0

Sehr vernünftige Antwort. :) TIL - scheint albern, aber leider. – erip

Antwort

0

sollten Diese

arbeiten
gcc: static __thread 

MSVC: static __declspec(thread) 

jedoch besser aus Leistungsgründen könnte es sein, es manuell zu handhaben. Verwenden Sie einen Vektor mit der Größe, die der Anzahl der Threads entspricht, und verwenden Sie die Threadnummer, um den Vektor zu indizieren. Wenn das Element NULL ist, muss der Thread es konstruieren.

Lesen Sie auch: How to define thread-local local static variables?

So etwas wie dies (bitte beachten Sie, dass es nicht getestet, und ich OMP mich nie benutzen, weil es nicht den Grad der Beherrschung bieten, dass ich es vorziehen, darüber zu haben, was tatsächlich passiert).

std::vector<Tree *> trees; 
trees.resize(omp_get_thread_limit()); 

#pragma omp parallel for 
    for (long i = 0; i < static_cast<long>(general_triangles.size()); ++i) 
    { 
     TrianglePointer tri = general_triangles[i]; 
     if (tri.GetClassification() == TO_CLASSIFY) 
     { 
      bool tri_has_correct_normal = true; 
      // --- Construct tree once per thread --- 
      Tree *& tree = trees[omp_get_thread_num()]; 
      if (tree == NULL) 
       tree = new Tree(*(gp_boolean_operator->mp_group_manager)); 
      if (tree->IsTriangleExternal(tri, tri_has_correct_normal)) 
      { 
       tri.SetClassification(IS_EXTERNAL); 
      } 
     } 
    } 

    // delete trees afterwards 
+0

Es ist nicht nötig, OpenMP zu verlassen. –

+0

Ja, da ist (oder sein kann) eine Notwendigkeit, weil das "statische" Schlüsselwort den Compiler veranlassen wird, einen Mutex einzufügen, der die Verarbeitung enorm verlangsamen wird. –

+0

Baum & * Baum? Bist du sicher? –

1

Betrachten ungetesteten Code wie folgt:

#pragma omp parallel 
{ 
// --- Construct one tree in each per thread --- 
    Tree tree(*(gp_boolean_operator->mp_group_manager)); 

#pragma omp for 
    for (long i = 0; i < static_cast<long>(general_triangles.size()); ++i) 
    { 
     TrianglePointer tri = general_triangles[i]; 
     if (tri.GetClassification() == TO_CLASSIFY) 
     { 
      bool tri_has_correct_normal = true; 

      if (tree.IsTriangleExternal(tri, tri_has_correct_normal)) 
      { 
       tri.SetClassification(IS_EXTERNAL); 
      } 
     } 
    } 
} 

Es zeigt, dass Sie portable all diese innen tun können, unabhängig vom Betriebssystem, OpenMP, und dass Sie keine unnötige statische Variable einzuführen.