7 Мая в 21:03
11 +1
0
Ответы
1
В текущем виде есть гонка данных на переменной `sum`: несколько потоков одновременно выполняют `sum += a[i]`, результат неопределён. Цель вычислить сумму ∑i=0n−1a[i]\sum_{i=0}^{n-1} a[i]i=0n1 a[i].
Быстрые варианты исправления:
1) Рекомендуемый (прост и эффективен):
#pragma omp parallel for reduction(+:sum)
for (int i=0;i<n;i++){
sum += a[i];
}
Убедитесь, что перед этим sum=0\text{sum}=0sum=0.
2) Атoмическое обновление (правильно, но медленнее из‑за синхронизации на каждой итерации):
#pragma omp parallel for
for (int i=0;i<n;i++){
#pragma omp atomic
sum += a[i];
}
3) Локальные суммы в каждом потоке + объединение (часто быстро и гибко):
double sum = 0.0;
#pragma omp parallel
{
double local = 0.0;
#pragma omp for
for (int i=0;i<n;i++) local += a[i];
#pragma omp atomic
sum += local;
}
4) Критическая секция (работает, но обычно медленнее, чем reduction/atomic):
#pragma omp parallel for
for (int i=0;i<n;i++){
#pragma omp critical
sum += a[i];
}
Замечания: для целочисленных сумм или когда порядок сложения не критичен используйте `reduction`. Для вещественных чисел результат может отличаться из‑за неассоциативности операций с плавающей точкой; если нужна детерминированность или повышенная точность — используйте аккумулирование в long double\text{long double}long double или деревообразное (tree) свёртывание.
7 Мая в 21:53
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир