OpenMP 并行缩减(最小)不正确的结果

OpenMP parallel reduction (min) incorrect result

我正在使用 OpenMP reduction(min) 在所有参与线程的并行部分中获得最少的锁获取次数。 在并行部分内打印每个线程计数器时,我得到了正确的结果,但在并行部分之后,最小计数器为 0。 这是代码:

    int counter = 0, maxV, minV;
    bool _continue = true;  //variable to indicate when one second is over

    #pragma omp parallel private(id) shared(lock, _continue) reduction(min:minV) reduction(+:counter) reduction(max:maxV)
    {
        id = omp_get_thread_num();
        
        if(id == 0)
        {
            auto start = std::chrono::high_resolution_clock::now(); //start time measurement
            while(_continue)
            {
                auto finish = std::chrono::high_resolution_clock::now();
                std::chrono::duration<double, std::micro> elapsed = finish - start;
                if(elapsed.count() > std::chrono::microseconds(sec).count())
                {
                    _continue = false;
                }
            }
        }
        else
        {
            while(_continue) //during timeframe, try to obtain lock as often as possible
            {
                lock.lock(id);
                lock.unlock(id);
                counter++;
            }
            minV = counter;
            maxV = counter;
        }
        #pragma omp critical
        {
            std::cout << id << ": " << minV << std::endl; 
        }
        
    }
    std::cout << minV << std::endl;

典型的输出是这样的:

0: 2147483647
7: 256985
4: 255973
1: 256975
6: 255740
5: 256658
3: 256856
2: 256943
0

因此,即使对于线程 0,即不获取锁而只是占用时间的线程,minV 也被正确初始化为缩减列表项类型 (int) 中的最大可表示数。

根据我选择的编译器选项,我可以将 minV 的结果(cout 中的最后一行)更改为以下值(总是错误...):

minV = 32767 | -std=c++14 -fopenmp

最小电压 = 0 | -std=c++14 -fopenmp -O3

minV = 32766 | -std=c++14 -fopenmp -Wall

minV = 32767 | -std=c++14 -fopenmp -Wall -pedantic -march=native -fconcepts

所以我认为它与我的编译器选项有关?奇怪的是,最大和总和的减少似乎工作正常......

感谢任何帮助。

您混淆了 OMP 内部使用的初始值和来自用户代码的初始值。部分减少是用内部值完成的,但在某些时候还必须减少 user-supplied 初始值。如果你不设置它,任何事情都可能发生。

这是一张可爱的照片:https://theartofhpc.com/pcse/omp-reduction.html#Initialvalueforreductions