我似乎不太了解嵌套有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条输出消息。为什么这两种情况下的输出不同?
答案 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
其中?
表示它可以是任何可用线程。