所以我有一小段代码:
int a = 10;
bool finished = false;
#pragma omp parallel num_threads(3) shared(a, finished)
{
while(!finished) {
#pragma omp single nowait
{
printf("[%d] a is: %d\n", omp_get_thread_num(), a);
a--;
finished = true;
}
}
}
输出是
[0] a is: 10
[2] a is: 10
[1] a is: 10
这根本不是我所期望的。我意识到,在退出while循环之前,所有线程都可以进入单个构造,但是为什么它们都说相同的A?进入的第二个线程应该有a=9,第三个线程应该有a=8。
我试过pragma omp flush和pragma omp atomic,但是没有用。我想在那个块中使用a进行比较(即if(a==10)),因此在另一个线程进入单个块时更新该值至关重要。我做错什么了?
最佳答案
代码的问题是single
指令基本上没有效果。通过指定nowait
子句,其他线程将不会在块的末尾等待,而是立即进入下一个循环迭代。
这意味着,到达single
构造的第一个线程将在第一次迭代中执行块。其余的线程将跳过块,并在第二次迭代中立即再次到达single
构造。剩下的两个线程中的一个也会进入块(因为这是一个新的迭代,因此也是块的另一次出现)。另一个在第三次迭代中再次跳过并立即进入。最后,所有线程几乎同时执行并打印a
的初始值,因为在这个时间点之前,没有一个线程成功地减少a
。
如果按如下方式交换a
块中的语句,您将看到single
正在更改。但是,这些值及其顺序将不确定。
#pragma omp single nowait
{
a--;
printf("[%d] a is: %d\n", omp_get_thread_num(), a);
finished = true;
}