在 openMP 中,如何确保线程在继续之前同步?
Posted
技术标签:
【中文标题】在 openMP 中,如何确保线程在继续之前同步?【英文标题】:In openMP how do I ensure threads are synchronized before continuing? 【发布时间】:2018-03-27 02:31:00 【问题描述】:我正在使用#pragma omp 屏障来确保我的所有并行线程在继续之前在同一点相遇(没有花哨的条件分支代码,只是直接循环),但我推测屏障编译指示实际上并不能保证同步性,只是完成,因为这些是我得到的结果:
0: func() size: 64 Time: 0.000414 Start: 1522116688.801262 End: 1522116688.801676
1: func() size: 64 Time: 0.000828 Start: 1522116688.801263 End: 1522116688.802091
线程 0 的启动速度比线程 1 快约 1 微秒,因此完成时间为 0.414 毫秒,这有点不切实际,顺便说一下,在单个内核/线程运行中,运行时间平均约为 0.800 毫秒。 (如果我的单位关闭,请原谅我,已经晚了)。
我的问题是:有没有办法确保在 openMP 中线程都同时启动?或者我是否必须引入另一个库,如 pthread 才能拥有此功能?
【问题讨论】:
你能发布你的循环吗?据我所知,没有允许您指定线程同时启动的并行库。 您要解决的实际问题是什么?请张贴minimal reproducible example 来说明您的问题。除了硬实时系统之外,您绝对不能确保多个线程同时启动。 您想如何保证这一点?如果线程数多于内核数怎么办?如果其他进程在同一个系统上运行(总是有一些,例如后台操作系统进程)怎么办? 如果您让所有线程在共享内存原子标志上忙于等待(又名旋转),您可能会更接近同时恢复所有线程。没有操作系统参与唤醒它们,只是来自一个核心的存储,如果所有其他核心都坐在pause
/cmp byte [flag], 0
/je .retry
busy-wait 循环中,它们几乎会同时看到。 (如果你愿意,可以用原子和_mm_pause()
在 C 中编写循环)。
【参考方案1】:
OpenMP 中的barrier
语句与其他语言一样,确保在所有线程都到达障碍之前没有线程继续进行。
它没有指定线程再次开始执行的顺序。据我所知,在 OpenMP 或 Pthread 库中手动调度线程是不可能的(见下面的评论)。
【讨论】:
使用 pthreads,如果您想控制唤醒哪个线程,您可以让每个线程递减一个共享计数器,然后在其自己的条件变量处停止。当一个线程发现它的递减使计数为零时,这意味着所有其他线程已经停止并等待它们的条件变量。 (或者在减量和条件变量之间暂停;不要在那里进行任何相关工作,这并不重要。)这基本上是一个手动实现的barrier
,最后一个线程可以使用它解除阻塞特定线程线程的条件变量。
可能还有更有效的方法来做到这一点,尤其是使用 C11 stdatomic
。或其他 POSIX 机制,如信号,例如将 SIGCONT 发送到另一个线程。以上是关于在 openMP 中,如何确保线程在继续之前同步?的主要内容,如果未能解决你的问题,请参考以下文章