Как я могу справиться с гонкой данных в 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];
}