在我的 C++ 应用程序开始附近,我的主线程使用 OMP 并行化多个 for 循环。在第一个并行化 for 循环之后,我发现所使用的线程在应用程序的持续时间内仍然存在,并且可以使用以下命令(在 CentOS 7 中工作)重用于从主线程执行的后续 OMP for 循环:
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
(or boost::thread
or std::thread
)不继承指针,因此产生一个新的池。其他 OpenMP 运行时也可能出现这种情况。
标准中有一个要求,基本上强制在大多数实现中执行这种行为。这是关于语义的线程私有变量以及如何在从同一线程分叉的不同并行区域中保留它们的值(OpenMP 标准,2.15.2 threadprivate指示 http://www.openmp.org/mp-documents/openmp-4.5.pdf#subsection.2.15.2):
非初始线程的 threadprivate 变量中的数据值保证在两个连续的活动之间持续存在parallel
仅当满足以下所有条件时才区域:
- Neither
parallel
区域嵌套在另一个显式并行区域内。
- 用于执行两者的线程数
parallel
地区是一样的。
- 用于执行两者的线程亲和性策略
parallel
地区是一样的。
- 的价值dyn-var封闭任务区域中的内部控制变量是false在进入两者时
parallel
地区。
如果这些条件全部成立,并且在两个区域中都引用了 threadprivate 变量,则在各自区域中具有相同线程号的线程将引用该变量的相同副本。
除了性能之外,这可能是在 OpenMP 运行时中使用线程池的主要原因。
现在,假设由两个单独的线程分叉的两个并行区域共享同一个工作线程池。第一个线程分叉了一个并行区域,并设置了一些线程私有变量。随后,同一个线程会分叉出第二个并行区域,并在其中使用这些 threadprivate 变量。但在两个并行区域之间的某个地方,第二个线程分叉出一个并行区域,并使用同一池中的工作线程。由于大多数实现在 TLS 中保留线程私有变量,因此无法再断言上述语义。一种可能的解决方案是为每个单独的线程向池中添加新的工作线程,这与创建新的线程池没有太大区别。
我不知道有任何解决方法可以使工作线程池共享。如果可能的话,它也不会是可移植的,因此 OpenMP 的主要优势将会丧失。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)