Search code examples
c++multithreadingopenmp

OpenMP conditional critical


First, bear in mind that I'm not a very frequent user of OpenMP... OK?

Now that we're past that, is there such thing as a conditional critical?
I am particularly interested in this line inside a parallelized for loop:

(...)

    #pragma omp critical
    myMapOfVectors[i].push_back(someNumber);

(...)

I would like to have it critical if and only if the threads running this specific line have the same i (because as I have been experiencing – and please correct me here if I'm wrong – multiple threads pushing back to the same vector is not thread safe and might cause a segfault).


Solution

  • What you need is to have a lock for each index i.

    // before you parallel region
    std::vector<omp_lock_t> myLocks(myMapOfVectors.size());
    for (size_t i = 0; i < myLocks.size(); ++i) {
        omp_init_lock(myLocks+i);
    }
    
    ...
    
    omp_set_lock(myLocks[i]);
    myMapOfVectors[i].push_back(someNumber);
    omp_unset_lock(myLocks[i]);
    
    ...
    
    // after your parallel region
    for (size_t i = 0; i < myLocks.size(); ++i) {
        omp_destroy_lock(myLocks+i);
    }
    

    A critical section is essentially just a single lock, by having multiple locks you are in essence emulating having a separate critical section for each index.

    Just keep in mind that locking can be quite slow (especially if there are collisions). You may be able to achieve better performance if you can partition your work ahead of time (i.e., each thread works on a different set of indexes i, or each thread has its own copy of myMapOfVectors that get combined later).