0

Some days ago it came to my mind, that a piece of code to implement a min/max reduction in OpenMP, that i used quite often, might actually not be correct:

In some cases, when the OpenMP min-max reduction clause was not available (old OpenMP version) or i also needed the index for the maximum value i used code like this:

#pragma omp parallel private(myMax,myMax_idx) shared(globalMax,globalMax_idx)
{
    #pragma omp for
    for (...) {
    }

    if (myMax >= globalMax) {
        #pragma omp critical
        {
            if ((myMax > globalMax)||(myMax == globalMax && globalMax_idx < myMax_idx) {
                globalMax = myMax;
                globalMax_idx = myMax_idx;
            }
        }
    }
}

Now it came to my mind, that this code might actually produce wrong results because shared variable does NOT mean that all threads access the same portion of memory, but they might use a private copy that might not be up to date with all other threads. So i need to use #pragma omp flush to synchronize the variable.

[...]
    #pragma omp flush(globalMax)
    if (myMax > globalMax) {
        #pragma omp critical
        {
            if (myMax > globalMax) globalMax = myMax;
        }
    }
[...]

In M. Süß et al, Common Mistakes in OpenMP and How To Avoid Them this implementation is described as

This is essentially a reimplementation of a reduction using the max operator.

But i wonder if this piece of code is correct because i don't see the writing thread flushing his version of globalMax to the memory.

Also in the case of searching the index i would need to also flush the globalMax_idx variable. Right?

This question is kind of related to

So if the Code from the "Common Mistakes in OpenMP" is assuming that the critical region does a flush is it really worth it to explicitly flush the globalMax-variable before the if?

What code should i use?

Community
  • 1
  • 1
MaPePeR
  • 931
  • 9
  • 18
  • 2
    Did you read Michael Klemm's answer to my question you linked to? Don't worry about `flush`. Move on... – Z boson Nov 19 '14 at 11:45
  • Yes, i did read the answer to your question, but for me a "just don't think about it - everything will be fine" is not really acceptable. i would like to be sure the code works instead of hoping. During our OpenMP course we encountered a lot of programs that had all variables shared, but because of private copys did not fail horrible like they should if you declare private variables as shared. This made me thinking. – MaPePeR Nov 19 '14 at 12:17
  • 2
    If you don't like the answer provided, go to the [OpenMP standard](http://www.openmp.org/mp-documents/OpenMP4.0.0.pdf) and read essentially the same thing for yourself in the section on memory consistency, 1.4.4, lines 21-29: "OpenMP programs that -do not use non-sequentially consistent atomic directives, -do not rely on the accuracy of a false result from omp_test*_lock, and - correctly avoid data races[...] ... any explicit flush operations in such programs are redundant'', or the section on flush (2.12.7, 137:10) "a flush region ... is implied.. at entry to&exit from.. critical regions". – Jonathan Dursi Nov 19 '14 at 16:42

0 Answers0