C++ 嵌套循环中未正确忽略内部循环的Pragma omp parallel

C++ 嵌套循环中未正确忽略内部循环的Pragma omp parallel,c++,multithreading,openmp,C++,Multithreading,Openmp,我试图实现以下代码,以了解如何通过嵌套循环管理OpenMP线程,其中每个内部/外部循环在函数及其调用方中分别实现 每个循环都用语句实现 #pragma omp parallel for,我假设忽略了内部循环的pragma 为了看到这一点,我在每个循环中打印了线程编号 然后,我可以看到以下内容,其中内部循环中的线程id始终为零,与调用方对应的线程编号不相同。为什么会发生这种情况 Calling 0 from 0 Calling 2 from 1 Calling 6 from 4 Calling 8

我试图实现以下代码,以了解如何通过嵌套循环管理OpenMP线程,其中每个内部/外部循环在函数及其调用方中分别实现

每个循环都用语句实现
#pragma omp parallel for
,我假设忽略了内部循环的
pragma

为了看到这一点,我在每个循环中打印了线程编号

然后,我可以看到以下内容,其中内部循环中的线程id始终为零,与调用方对应的线程编号不相同。为什么会发生这种情况

Calling 0 from 0
Calling 2 from 1
Calling 6 from 4
Calling 8 from 6
Calling 4 from 2
Calling 7 from 5
Calling 5 from 3
    Calling 0 from 0  // Expecting 3
    Calling 1 from 0
    Calling 2 from 0
    Calling 3 from 0
    Calling 0 from 0
    Calling 1 from 0
    Calling 2 from 0
    Calling 3 from 0
    Calling 0 from 0
    Calling 0 from 0
    Calling 0 from 0
    Calling 1 from 0
    Calling 2 from 0
    Calling 3 from 0
Calling 9 from 7
    Calling 1 from 0 // Expecting 7
    Calling 2 from 0
    Calling 3 from 0
    Calling 0 from 0
Calling 3 from 1
    Calling 0 from 0 // Expecting 1
    Calling 1 from 0
    Calling 2 from 0
    Calling 1 from 0
    Calling 2 from 0
    Calling 3 from 0
    Calling 3 from 0
    Calling 1 from 0
    Calling 2 from 0
    Calling 3 from 0
    Calling 0 from 0
    Calling 1 from 0
    Calling 2 from 0
    Calling 3 from 0
    Calling 0 from 0
    Calling 1 from 0
    Calling 2 from 0
    Calling 3 from 0
Calling 1 from 0
    Calling 0 from 0
    Calling 1 from 0
    Calling 2 from 0
    Calling 3 from 0
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
const size_t kM=4;
结构垫
{
国际元素[kM];
材料(施工材料和副本)
{
for(size_t i=0;ielem[i]=copy.elem[i];
}
Mat()
{

对于(size_t i=0;i,除非您为OpenMP提供特殊选项,否则它会尝试在编译时分割工作,而嵌套并行很难实现,因此它甚至不会尝试


您可以参考以获取建议(例如,在OpenMP 3.0+中使用
折叠

,我不确定我是否理解您的期望,但您得到的结果完全符合预期

默认情况下,OpenMP嵌套并行被禁用,这意味着任何嵌套的
并行
区域将创建一个线程组,其数量与外部级别遇到它们的线程数量相同

在您的例子中,最外层的
并行
区域创建一个由8个线程组成的团队。每个线程都将到达最内层的
并行
区域,并创建一个第二级1线程团队。每个第二级线程在其自己的团队中排名为0,因此打印的0为0

对于使用g++9.3.0编译的完全相同的代码,通过设置两个环境变量
OMP_NUM_THREADS
OMP_NESTED
,我得到以下结果:

OMP_NUM_THREADS="2,3" OMP_NESTED=true ./a.out 
Calling 0 from 0
Calling 5 from 1
    Calling 0 from 0
    Calling 1 from 0
    Calling 2 from 1
    Calling 0 from 0
    Calling 1 from 0
    Calling 3 from 2
    Calling 3 from 2
    Calling 2 from 1
Calling 6 from 1
Calling 1 from 0
    Calling 0 from 0
    Calling 1 from 0
    Calling 3 from 2
    Calling 2 from 1
Calling 2 from 0
    Calling 0 from 0
    Calling 1 from 0
    Calling 2 from 1
    Calling 3 from 2
    Calling 0 from 0
    Calling 1 from 0
    Calling 3 from 2
    Calling 2 from 1
Calling 3 from 0
Calling 7 from 1
    Calling 0 from 0
    Calling 3 from 2
    Calling 2 from 1
    Calling 3 from 2
    Calling 0 from 0
    Calling 1 from 0
    Calling 1 from 0
    Calling 2 from 1
Calling 4 from 0
Calling 8 from 1
    Calling 0 from 0
    Calling 3 from 2
    Calling 2 from 1
    Calling 2 from 1
    Calling 0 from 0
    Calling 1 from 0
    Calling 3 from 2
    Calling 1 from 0
Calling 9 from 1
    Calling 2 from 1
    Calling 0 from 0
    Calling 1 from 0
    Calling 3 from 2

也许这更符合您的预期?

内部循环中显示的数字的含义是什么?在我的例子中,所有内容都显示为0。但是,我们有8个线程并行执行外部循环(数字0-7)。我怀疑内部循环是否由编号为0的同一线程处理。您的误解可能是因为
omp\u thread\u num()
返回了最近遇到的团队(最内部的团队)中的线程id,不一定是第一个。因此,您看到的0与此完全一致,因为所有线程都是第二级并行区域上的主线程,每个区域有8个不同的团队,每个团队有1个线程。在我的版本中,我们创建了2个第二级团队,每个团队有3个线程。这就是为什么您看到ID从0到2的原因。这有意义吗?啊,I g说到这里。谢谢你的评论。当我删除了内部循环的pragma语句时,我的期望值就来了。这是否意味着在内部/外部循环中使用
omp parallel for
语句(没有任何特定选项)会在内部循环中产生额外的开销?