vendredi 10 septembre 2021

OpenMP reduction: min gives incorrect result

I want to use an OpenMP reduction in a parallel region, outside a for loop. According to the OpenMP reference, reduction clauses can be used in parallel regions, so no for loop or sections should be necessary.

However, when using an OpenMP reduction (min:...) in a parallel region, I'm getting incorrect results. If I use exactly the same structure for a reduction (max:...) however, the result is correct. If I use a loop for the min reduction (#pragma omp for reduction (min:...)), the results are correct, but I don't think that should be necessary. Here's my code:

#include <omp.h>
#include <iostream>
#include <limits>
#include <algorithm>

int main(){
    auto minVar { std::numeric_limits<int>::max() };
    auto maxVar { std::numeric_limits<int>::min() };
    auto minVarLoop { std::numeric_limits<int>::max() };

    #pragma omp parallel
    {
        int threadNo { omp_get_thread_num() };

        #pragma omp reduction (min:minVar)
        minVar = std::min(minVar, threadNo);
        // minVar = minVar < threadNo ? minVar : threadNo; // also doesn't work
        
        #pragma omp for reduction(min:minVarLoop)
        for (int i=0; i<omp_get_num_threads(); ++i){
            minVarLoop = std::min(minVarLoop, threadNo);
        }
        
        #pragma omp reduction (max:maxVar)
        maxVar = std::max(maxVar, threadNo);
    }
    std::cout
        <<   "min thread num: " << minVar
        << "\nmax thread num: " << maxVar
        << "\nmin thread num from Loop: " << minVarLoop
        << "\n";

    return 0;
}

The expected output, with 16 threads, is

min thread num: 0
max thread num: 15
min thread num from Loop: 0

The output I get is

min thread num: 12 // or any other number between 0 and 15
max thread num: 15
min thread num from Loop: 0

I'm compiling using g++ version 10.3.0 on Ubuntu 21.04, using only the flag -fopenmp.

What am I overlooking?

EDIT: not initialising minVar, i.e. using int minVar; somehow makes it work, but I don't find that a satisfying solution. Also, attempting the same with maxVar, makes those results incorrect. Oh my.

Aucun commentaire:

Enregistrer un commentaire