Home > Parallel Programming > Common Mistakes in Using OpenMP 2: Atomic

Common Mistakes in Using OpenMP 2: Atomic

February 20th, 2006

The following code finds good members in array
member[] and stores the indices of the good members in array
good_members[].

#define N 1000
struct data member[N];
int good_members[N];
int pos = 0;
void find_good_members()
{
    for (i=0; i < N; i++) {
        if (is_good(member[i])) {
            good_members[pos] = i;
            pos ++;
        }
    }
}

The following is a navie way of parallelizing the above code,

#define N 1000
struct data member[N];
int good_members[N];
int pos = 0;
void find_good_members()
{
    #pragma omp parallel for
    for (i=0; i < N; i++) {
        if (is_good(member[i])) {
            good_members[pos] = i;   // line a
            #pragma omp atomic
            pos ++;                  // line b
        }
    }
}

In order to avoid data races between different updates of
global variable pos, the code puts the increment (at line b) in a
atomic construct. However, the code does not work, because there is a
data race between the read of pos at line a and write of pos at line b.

Changing the body of the if statement to the following gives the correct result.

      int mypos;
      #pragma omp critical
      {
          mypos = pos;
          pos ++;
      }
      good_members[mypos] = i;

In OpenMP 2.5 (the latest Specification), inside a parallel region, the only place where you can safely get the
value of a variable that is updated in an atomic region is another
atomic region.

Categories: Parallel Programming Tags:
  1. No comments yet.
  1. No trackbacks yet.