Execute piece of code once per thread in OpenMP without default constructor

醉酒当歌 提交于 2019-12-24 05:46:18

问题


I try to write a parallel for loop using openMP V.2.0. In the middle of the parallel region I construct an Object which I would like to be constructed once per thread.

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

Is there any keyword for constructing tree once per thread?

Do you suggest to use bood_thread_ptr instead?


回答1:


Consider untested code like this :

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

It shows that you can do all this inside portable, OS independent, OpenMP, and that you don't introduce an unnecessary static variable.




回答2:


This should work

gcc: static __thread

MSVC: static __declspec(thread)

However, for performance reasons it might be better to handle it manually. Use a vector with size that corresponds to the number of threads, and use the thread number to index the vector. If the element is NULL, the thread must construct it.

Also read: How to define thread-local local static variables?

Something like this (please note that it is untested, and I never use OMP myself because it does not offer the degree of control that I prefer to have over what actually happens).

 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


来源:https://stackoverflow.com/questions/40586798/execute-piece-of-code-once-per-thread-in-openmp-without-default-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!