-2

I was reading about OpenMP and shared memory programming and fell over this pseudo code that has an integer x and two threads

thread 1
x++;

thread 2
x--;

This will lead to a race condition, but can be avoided. I want to avoid it using OpenMP, how should it be done?

This is how I think it will be avoided:

int x;
#pragma omp parallel shared(X) num_threads(2)

int tid = omp_get_thread_num();
if(tid == 1)
    x++;
else
    x--;

I know that by eliminating the race condition will lead to correct execution but also poor performance, but I don't know why?

Matthieu Brucher
  • 21,634
  • 7
  • 38
  • 62
George W
  • 51
  • 1
  • 7
  • The code you show has *exactly* the problem you describe; it doesn't avoid it at all. It's not a problem if `x` is declared as a suitable `std::atomic` integer, but since you haven't shown us what type it is, we can only gues... – Toby Speight Aug 17 '17 at 14:24
  • @TobySpeight: I have shown that x is an integer. Furthermore, that's the snippet that were in my reading material. – George W Aug 17 '17 at 16:12
  • @TobySpeight wrong - *The thread number is an integer between 0 and one less than the value returned by omp_get_num_threads, inclusive.* – Zulan Aug 17 '17 at 16:26
  • The question makes no sense to me. Either your reading material is really bad, or you need to revisit the basics. – Zulan Aug 17 '17 at 16:27
  • @TobySpeight: so the solution is to change `if(tid == 1)` to `if(tid == 0)` – George W Aug 17 '17 at 21:26
  • @Zulan: I got the pseudo code from my reading material – George W Aug 17 '17 at 21:26

1 Answers1

1

If more than one thread is modifying x, the code is at risk from a race condition. Taking a simplified version of your example

int main()
{
    int x = 0;

    #pragma omp parallel sections
    {
        #pragma omp section {
            ++x;
        }
        #pragma omp section {
            --x;
        }
    }

    return x;
}

The two threads modifying x may be interleaved with each other, meaning that the result will not necessarily be zero.

One way to protect the modifications is to wrap the read-modify-write code in a critical region.

Another, that suitable for the simple operations here, is to mark the ++ and -- lines with #pragma omp atomic - that will use platform-native atomic instructions where they exist, which is lightweight compared to a critical region.

Another approach that usually works (but isn't strictly guaranteed by OpenMP) is to change the type used for x to a standard atomic type. Simply changing it from int to std::atomic<int> gives you indivisible ++ and -- operators which you can use here.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
  • The question omits the idiomatic solution: `#pragma omp atomic`. [Using `std::atomic` with OpenMP is not explicitly specified](https://stackoverflow.com/a/41316118/620382). – Zulan Aug 18 '17 at 13:00