与for循环并行的pragma omp的行为

时间:2019-01-03 03:46:20

标签: c++ parallel-processing openmp

我似乎不太了解嵌套有for循环的openmp并行构造的行为。考虑以下代码:

std::size_t idx;
std::size_t idx2;
omp_set_num_threads( 2 );

#pragma omp parallel default(shared) private(idx, idx2)
{

  for(std::size_t idx=0;idx<3;idx++)
  {
    for(std::size_t idx2=0;idx2<4;idx2++)
    {
      LOG("From thread "+std::to_string(omp_get_thread_num())+" idx "+std::to_string(idx)+" idx2 "+std::to_string(idx2));
    }
  }
}

这将产生以下输出:

From thread 0 idx 0 idx2 0
From thread 1 idx 0 idx2 0
From thread 0 idx 0 idx2 1
From thread 1 idx 0 idx2 1
From thread 0 idx 0 idx2 2
From thread 1 idx 0 idx2 2
From thread 0 idx 0 idx2 3
From thread 1 idx 0 idx2 3
From thread 0 idx 1 idx2 0
From thread 1 idx 1 idx2 0
From thread 0 idx 1 idx2 1
From thread 1 idx 1 idx2 1
From thread 0 idx 1 idx2 2
From thread 1 idx 1 idx2 2
From thread 0 idx 1 idx2 3
From thread 1 idx 1 idx2 3
From thread 0 idx 2 idx2 0
From thread 1 idx 2 idx2 0
From thread 0 idx 2 idx2 1
From thread 1 idx 2 idx2 1
From thread 0 idx 2 idx2 2
From thread 1 idx 2 idx2 2
From thread 0 idx 2 idx2 3
From thread 1 idx 2 idx2 3

上面似乎发生的事是,分配了2个线程来执行两个嵌套循环,结果它们产生了上述输出(总共2 * 3 * 4 = 24条日志消息),这很简单。

但是现在考虑以下代码,其中内部for循环被声明为pragma omp for

std::size_t idx;
std::size_t idx2;    
omp_set_num_threads( 2 );

#pragma omp parallel default(shared) private(idx, idx2)
{

  for(std::size_t idx=0;idx<3;idx++)
  {
    #pragma omp for
    for(std::size_t idx2=0;idx2<4;idx2++)
    {
      LOG("From thread "+std::to_string(omp_get_thread_num())+" idx "+std::to_string(idx)+" idx2 "+std::to_string(idx2));
    }
  }
}

这将产生以下3 * 4 = 12条日志消息:

From thread 0 idx 0 idx2 0
From thread 1 idx 0 idx2 2
From thread 0 idx 0 idx2 1
From thread 1 idx 0 idx2 3
From thread 0 idx 1 idx2 0
From thread 1 idx 1 idx2 2
From thread 0 idx 1 idx2 1
From thread 1 idx 1 idx2 3
From thread 0 idx 2 idx2 0
From thread 0 idx 2 idx2 1
From thread 1 idx 2 idx2 2
From thread 1 idx 2 idx2 3

我本来希望再次将两个线程分配给与两个内部for循环相对应的代码,并再次获得24条输出消息。为什么这两种情况下的输出不同?

1 个答案:

答案 0 :(得分:1)

在第一种情况下,#pragma omp parallel在每个线程上运行一次整个并行区域。这意味着两个线程将完全针对循环运行,因此每个线程应生成4 * 3 = 12行输出。

在第二种情况下,内部#pragma omp for告诉计算机,idx2上的内部for循环应在可用线程之间分配。因此,代替两个线程都执行从0到idx2的内部循环,内部循环的每个迭代将只执行一次。

在第二个输出中,我们应该看到idx2的所有值对于idx的每个值以及从任何可用线程中都被打印一次。

例如如果idx只能为零,则输出可能类似于:

From thread ? idx 0 idx2 0
From thread ? idx 0 idx2 1
From thread ? idx 0 idx2 2
From thread ? idx 0 idx2 3

其中?表示它可以是任何可用线程。