如何在工作线程中重用主线程创建的OMP线程池? P>在我的C++应用程序的开头,我的主线程使用OMP来并行化几个循环。在第一个并行for循环之后,我看到在应用程序期间使用的线程仍然存在,并使用以下命令(在CentOS 7中工作)重新用于从主线程执行的后续OMP for循环:

如何在工作线程中重用主线程创建的OMP线程池? P>在我的C++应用程序的开头,我的主线程使用OMP来并行化几个循环。在第一个并行for循环之后,我看到在应用程序期间使用的线程仍然存在,并使用以下命令(在CentOS 7中工作)重新用于从主线程执行的后续OMP for循环:,c++,multithreading,boost,openmp,C++,Multithreading,Boost,Openmp,稍后在我的程序中,我从主线程启动了一个boost线程,在该线程中,我使用OMP并行化for循环。此时,我看到创建了一组全新的线程,这有相当大的开销 是否可以使boost线程内的OMP parallel for循环重用主线程创建的原始OMP线程池 编辑:一些伪代码: myFun(data) { // Want to reuse OMP thread pool from main here. omp parallel for for(int i = 0; i < N;

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

是否可以使boost线程内的OMP parallel 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();


}
myFun(数据)
{
//要从这里重用主线程池中的OMP线程池。
并行计算
对于(int i=0;i
OpenMP与其他线程机制的交互被故意排除在规范之外,因此严重依赖于实现。GNU OpenMP运行时在TLS中保留一个指向线程池的指针,并将其向下传播(嵌套)团队。通过
pthread\u create
(或
boost::thread
std::thread
)启动的线程不会继承指针,因此会生成新池。其他OpenMP运行时可能也是如此

标准中有一个要求,基本上强制大多数实现中都有这样的行为。这是关于threadprivate变量的语义,以及它们的值如何在从同一线程分叉的不同并行区域之间保留(OpenMP standard,):

只有在满足以下所有条件的情况下,才能保证非初始线程的threadprivate变量中的数据值在两个连续的活动
并行
区域之间保持不变:

  • parallel
    区域都没有嵌套在另一个显式并行区域内
  • 用于执行两个
    并行
    区域的线程数相同
  • 用于执行两个
    并行
    区域的线程关联策略相同
  • 封闭任务区域中dyn var内部控制变量的值在两个
    平行
    区域的输入处为假
如果这些条件都成立,并且两个区域都引用了threadprivate变量,那么在各自区域中具有相同线程编号的线程将引用该变量的相同副本

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

现在,假设由两个独立线程分叉的两个并行区域共享同一个工作线程池。第一个线程分叉了一个并行区域,并设置了一些threadprivate变量。稍后,第二个并行区域由同一线程分叉,在这里使用这些threadprivate变量。但是在两个并行区域之间的某个地方,第二个线程分叉了一个并行区域,并且使用了来自同一池的工作线程。由于大多数实现在TLS中保留threadprivate变量,因此无法再断言上述语义。一种可能的解决方案是为每个单独的线程向池中添加新的工作线程,这与创建新的线程池没有太大区别


我不知道有什么办法可以让工作线程池共享。如果可能,它将不可移植,因此OpenMP的主要优点将丢失。

OpenMP与其他线程机制的交互不属于规范的一部分,因此严重依赖于实现。GNU OpenMP运行时在TLS中保留一个指向线程池的指针,并将其向下传播(嵌套)团队。通过
pthread\u create
(或
boost::thread
std::thread
)启动的线程不会继承指针,因此会生成新池。其他OpenMP运行时可能也是如此。@HristoIliev谢谢,这也是我从阅读中收集到的。你知道这方面有什么解决办法吗?我可以修改我的应用程序,使boost::thread实例保持活动状态,以重用其OMP线程池,但我希望能找到一个快速修复方法。我不知道有什么解决方法。此外,从最终用户的角度来看,OpenMP运行时应该是一个黑匣子,这样范例才能保持可移植性。@HristoIliev这是公平的。我不明白他们为什么不让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();


}