Search code examples
c++visual-studioopenmp

c++ logging from parallelized loop


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.


Solution

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