虽然
omp_thread_num
维护了一个完整的迭代,但相同的底层线程不一定会执行。
这让我想知道 omp 如何处理非 omp 线程本地变量,即
__thread int;
或 errno
,它们是底层线程的本地线程。
我在文档中找不到信息,但好像是
#pragma omp parallel for
for (int i = 0; i < 10000; ++i) {
// exec by omp thread 1, using underlying thread a
fileptr = fopen(filenames[i], "rb");
variable_heavy_op(); // or just yield, or nothing,
// exec by omp thread 1, using underlying thread b,
if (!fileptr) // local to omp thread 1
perror(filename[i]); // // uses errno, local to underlying thread b,
}
调试罕见的线程错误会非常痛苦。
errno
是一个灾难性的设计选择,我知道,但有些废话是难以避免的。另一个例子是读取 pthreads 中的 try lock 操作的结果,或者将 omp 与任何非 omp 线程原语或派生库(如标准模板库)一起使用。
问题是,我的断言是否正确。或者简化。如果我创建一个 __thread 变量(非 omp 线程绑定变量)它如何与 omp 线程池交互?
这个问题似乎有很多问题,对基于 OpenMP 的线程的工作原理存在一些潜在的误解。具体来说,我看不出执行
fopen
的线程与执行 perror
的线程有何不同,因为两者都在同一个循环迭代中。
但是,为了澄清线程数和线程局部变量之间的关系,请注意 OpenMP 标准 中的这段摘录:
非初始线程的线程
变量中的数据值保证仅在满足以下所有条件时在两个连续的活动threadprivate
区域之间持续存在:parallel
区域都没有嵌套在另一个显式parallel
区域中;parallel
- 用于执行两个
区域的线程数相同;parallel
- 用于执行两个
区域的线程关联策略是相同的;parallel
- 封闭的
区域中的dyn-var
内部控制变量的值在进入两个task
区域时都是假的;和parallel
- 在两个
区域之间没有遇到没有嵌套在teams
构造内部的target
构造。parallel
- 既不调用
也不调用omp_pause_resource
例程。omp_pause_resource_all
如果这些条件都成立,并且如果在两个区域都引用了一个
变量,那么在各自区域中具有相同线程号的线程将引用该变量的相同副本。threadprivate
换句话说:在正常情况下,具有相同线程局部变量的相同底层线程在所有
parallel
部分服务相同的 OpenMP 线程数