在没有默认构造函数的OpenMP中,每个线程执行一次代码

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

本文关键字:执行 线程 代码 一次 默认 构造函数 OpenMP      更新时间:2023-10-16

我尝试使用openMP V.2.0编写并行for循环。在并行区域的中间,我构造了一个对象,我希望每个线程构造一次。

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

是否有任何关键字构造树一次每个线程?

你建议使用bood_thread_ptr来代替吗?

像这样考虑未测试的代码:

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

它表明您可以在可移植的、独立于操作系统的OpenMP中完成所有这些工作,并且您不需要引入不必要的静态变量。

应该可以了

gcc: static __thread
MSVC: static __declspec(thread)

然而,出于性能原因,手动处理它可能更好。使用大小与线程数相对应的向量,并使用线程数对向量进行索引。如果元素为NULL,线程必须构造它。

另请阅读:如何定义线程局部局部静态变量?

类似这样的东西(请注意,它是未经测试的,我自己从来没有使用过OMP,因为它没有提供我喜欢的控制程度,而不是实际发生的事情)。

 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