I have a parallel for loop and ONCE for looping I'd like to log some details.
first_iteration = true;
#pragma omp parallel for schedule(runtime)
for (int j = 0; j < items.size(); j++) {
if (first_iteration) {
FILE_LOG(logINFO) << "blablabla";
first_iteration = false;
}
// do something
}
But it is always logged several times (probably number of thread times). And I have a suspicion that time to time it throws a segfault.
I've read a possible solution with temp variable and #pragma omp atomic read
and write
. But it doesn't seem to work with Visual Studio 19 (c++std14):
error C3005: 'read': unexpected token encountered on OpenMP 'atomic' directive`.
I need it work also in g++ 11.3.0.
If you want to stick with OpenMP atomics, try this. It uses a test and test-and-set logic to avoid cache-line bouncing and needless synchronization overhead.
int main()
{
int iteration = 0;
# pragma omp parallel for
for(int j = 0; j < 100; j++) {
int own_iteration;
# pragma omp atomic read relaxed
own_iteration = iteration;
if(own_iteration == 0) {
# pragma omp atomic update relaxed capture
own_iteration = iteration += 1;
if(own_iteration == 1)
std::cout << "blablabla\n";
}
}
}
You can make the code simpler with C++-11 atomics.
#include <atomic>
int main()
{
std::atomic<bool> first_iteration = true;
# pragma omp parallel for
for(int j = 0; j < 100; j++) {
if(first_iteration.load(std::memory_order_relaxed)
&& first_iteration.exchange(false, std::memory_order_relaxed)) {
std::cout << "blablabla\n";
}
}
}
Of course "first iteration" doesn't really mean much in fully parallel execution. You might as well check if(j == 0)
and be done with it.