Search code examples
openmpatomic

OpenMP atomic compare and swap


I have a shared variable s and private variable p inside parallel region.

How can I do the following atomically (or at least better than with critical section):

if ( p > s )
    s = p;
else
    p = s;

I.e., I need to update the global maximum (if local maximum is better) or read it, if it was updated by another thread.


Solution

  • OpenMP 5.1 introduced the compare clause which allows compare-and-swap (CAS) operations such as

    #pragma omp atomic compare
    if (s < p) s = p;
    

    In combination with a capture clause, you should be able to achieve what you want:

    int s_cap;
    
    // here we capture the shared variable and also update it if p is larger
    #pragma omp atomic compare capture
    {
       s_cap = s;
       if (s < p) s = p;
    }
    
    // update p if the captured shared value is larger
    if (s_cap > p) p = s_cap;
    

    The only problem? The 5.1 spec is very new and, as of today (2020-11-27), none of the widespread compilers, i.e., those available on Godbolt, supports OpenMP 5.1. See here for a more or less up-to-date list. Adding compare is still listed as an unclaimed task on Clang's OpenMP page. GCC is still working on full OpenMP 5.0 support and the trunk build on Godbolt doesn't recognise compare. Intel's oneAPI compiler may or may not support it - it's not available on Godbolt and I can't get it to compile OpenMP code.

    Your best bet for now is to use atomic capture combined with a compiler-specific CAS atomic, possibly in a loop.