考虑以下情况:
函数A创建一个OMP并行区域层,每个OMP线程调用一个函数B,它本身包含另一层OMP并行区域。
然后,如果在函数B的并行区域内存在OMP临界区域,那么该区域对于由函数A和B创建的所有线程是“全局”的,或者它仅仅是本地函数B ?
如果B是一个pre-bulit函数(例如静态或动态链接库)怎么办?
答案 0 :(得分:4)
OpenMP中的关键区域具有全局绑定,并且它们的范围扩展到具有相同名称的所有关键构造(在这方面,所有未命名的构造共享相同的特殊内部名称),无论它们在代码中出现在何处。您可以在OpenMP specification的相应绑定部分中了解每个构造的绑定。对于critical
构造,您有:
critical
区域的绑定线程集是所有线程。区域执行仅限于程序中所有线程中的单个线程,而不考虑线程所属的团队。( HI:强调我的)
这就是为什么强烈建议应该使用命名的critical
区域,特别是如果受保护资源集是不相交的,例如:
// This one located inside a parallel region in fun1
#pragma omp critical(fun1)
{
// Modify shared variables a and b
}
...
// This one located inside a parallel region in fun2
#pragma omp critical(fun2)
{
// Modify shared variables c and d
}
命名区域消除了两个不相关的关键构造可能相互阻塞的可能性。
至于问题的第二部分,为了支持OpenMP规范的动态范围要求,关键区域通常使用在运行时解析的命名互斥锁来实现。因此,可以在预构建的库函数和代码中使用同名关键区域,只要两个代码使用相同的OpenMP运行时,它就可以按预期工作,例如两者都是使用相同的编译器套件构建的。通常无法保证跨套件OpenMP兼容性。此外,如果在B()
中有一个未命名的关键区域,它将干扰其余代码中的所有未命名的关键区域,无论它们是否属于属于用户代码的相同库代码。