Как я могу справиться с гонкой данных в OpenMP?

Я пытаюсь использовать OpenMP для добавления чисел в массив. Ниже приведен мой код:

  int* input = (int*) malloc (sizeof(int)*snum);
  int sum = 0;
  int i;
  for(i=0;i<snum;i++){
      input[i] = i+1;
  }
  #pragma omp parallel for schedule(static)
  for(i=0;i<snum;i++)
  {
      int* tmpsum = input+i;
 sum += *tmpsum;
  }

это не дает правильного результата для sum. Что случилось?

2 ответов


ваш код в настоящее время имеет гонки, поэтому результат неверен. Чтобы проиллюстрировать, почему это так, давайте используем простой пример:

вы работаете на 2 потоках, а массив -int input[4] = {1, 2, 3, 4};. Вы инициализируете sum до 0 правильно и готовы начать цикл. На первой итерации вашего цикла поток 0 и поток 1 читают sum из памяти 0, а затем добавить их элемент sum, и записать его обратно в память. Однако, это означает, что поток 0 пытается писать sum = 1 в память (первый элемент 1 и sum = 0 + 1 = 1), в то время как поток 1 пытается написать sum = 2 в память (второй элемент 2 и sum = 0 + 2 = 2). Конечный результат этого кода зависит от того, какой из потоков завершается последним, и поэтому записывается в память последним, что является условием гонки. Не только это, но и в данном конкретном случае ни один из ответов, которые может дать код, не являются правильными! Есть несколько способов чтобы обойти это; я подробно остановлюсь на трех основных ниже:

#pragma omp critical:

в OpenMP есть то, что называется


использовать reduction п. (описание в MSDN).

int* input = (int*) malloc (sizeof(int)*snum);
int sum = 0;
int i;
for(i=0;i<snum;i++){
    input[i] = i+1;
}
#pragma omp parallel for schedule(static) reduction(+:sum)
for(i=0;i<snum;i++)
{
    sum += input[i];
}