c++ - 如何在工作线程中重用主线程创建的 OMP 线程池?

标签 c++ multithreading boost openmp

在我的 C++ 应用程序开始时,我的主线程使用 OMP 并行化多个 for 循环。在第一个并行化的 for 循环之后,我看到所使用的线程在应用程序的持续时间内仍然存在,并被用于从主线程执行的后续 OMP for 循环,使用命令(在 CentOS 7 中工作):

for i in $(pgrep myApplication); do ps -mo pid,tid,fname,user,psr -p $i;done

稍后在我的程序中,我从主线程启动了一个 boost 线程,在其中我使用 OMP 并行化了一个 for 循环。此时,我看到创建了一组全新的线程,这有相当多的开销。

是否可以使boost线程中的OMP并行for循环重用主线程创建的原始OMP线程池?

编辑:一些伪代码:

myFun(data)
{

    // Want to reuse OMP thread pool from main here.
    omp parallel for
    for(int i = 0; i < N; ++i)
    {
       // Work on data
    }

}


main
{

    // Thread pool created here.
    omp parallel for
    for(int i = 0; i < N; ++i)
    {
        // do stuff
    }


    boost::thread myThread(myFun) // Constructor starts thread.

    // Do some serial stuff, no OMP.

    myThread.join();


}

最佳答案

OpenMP 与其他线程机制的交互被故意排除在规范之外,因此在很大程度上取决于实现。 GNU OpenMP 运行时在 TLS 中保留指向线程池的指针并将其传播到(嵌套的)团队。通过 pthread_create(或 boost::threadstd::thread)启动的线程不会继承该指针,因此会生成一个新池。其他 OpenMP 运行时可能也是这种情况。

标准中有一项要求基本上在大多数实现中强制执行此类行为。它是关于 threadprivate 变量的语义以及它们的值如何在从同一线程派生的不同并行区域中保留(OpenMP 标准,2.15.2 threadprivate Directive):

The values of data in the threadprivate variables of non-initial threads are guaranteed to persist between two consecutive active parallel regions only if all of the following conditions hold:

  • Neither parallel region is nested inside another explicit parallel region.
  • The number of threads used to execute both parallel regions is the same.
  • The thread affinity policies used to execute both parallel regions are the same.
  • The value of the dyn-var internal control variable in the enclosing task region is false at entry to both parallel regions.

If these conditions all hold, and if a threadprivate variable is referenced in both regions, then threads with the same thread number in their respective regions will reference the same copy of that variable.

除了性能之外,这可能是在 OpenMP 运行时中使用线程池的主要原因。

现在,想象一下由两个独立线程 fork 的两个并行区域共享同一个工作线程池。第一个线程 fork 了一个并行区域,并设置了一些线程私有(private)变量。后来,同一个线程 fork 出第二个并行区域,其中使用了那些线程私有(private)变量。但是在两个并行区域之间的某处,一个并行区域由第二个线程 fork ,并且使用来自同一池的工作线程。由于大多数实现在 TLS 中保留 threadprivate 变量,因此不再断言上述语义。一种可能的解决方案是为每个单独的线程向池中添加新的工作线程,这与创建新的线程池没有太大区别。

我不知道有任何解决方法可以共享工作线程池。如果可能的话,它也不是可移植的,因此将失去 OpenMP 的主要优势。

关于c++ - 如何在工作线程中重用主线程创建的 OMP 线程池?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38254882/

相关文章:

c++ - 如何知道异步状态机何时终止。 ( boost::状态图)

c++ - STL 或 BOOST 是否提供任何干净的方法来获取排序顺序而无需重新排序原始序列?

c++ - 如何使用 C++ 获取 SQL SERVER 安装路径?

c++ - C++中的类方法错误

c++ - 程序在控制台中挂起,同时在 C++ 中提供较大的输入大小

c++ - 类模板特化中的成员函数语法

c++ - 在 C++11 中通过对 std::thread 的引用传递对象

C++ 管理共享对象的句柄问题

python - 为什么 Python threading.Condition() notify() 需要锁?

c++ - boost 反序列化优化?