所以我有一小段代码:

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;
}

07-28 03:05
查看更多