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
).
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).