Чем firstprivate и lastprivate отличаются от частных предложений в OpenMP?
Я посмотрел на официальные определения, но я все еще в замешательстве.
firstprivate
Указывает, что каждый поток должен иметь свой собственный экземпляр переменной и что переменная должна быть инициализирована значением переменной, поскольку она существует до параллельной конструкции.
Для меня это звучит очень похоже на личное. Я искал примеры, но я не понимаю, как это особенное или как его можно использовать.
lastprivate
: Указывает, что версия переменной окружающего контекста установлена равной частной версии любого потока, выполняющего последнюю итерацию (конструкция цикла for) или последний раздел (разделы #pragma).
Я чувствую, что понимаю это немного лучше из-за следующего примера:
#pragma omp parallel
{
#pragma omp for lastprivate(i)
for (i=0; i<n-1; i++)
a[i] = b[i] + b[i+1];
}
a[i]=b[i];
Итак, в этом примере я понимаю, что lastprivate
позволяет i
должен быть возвращен за пределы цикла как последнее значение.
Я только начал изучать OpenMP сегодня.
3 ответа
private
переменные не инициализируются, т.е. они начинаются со случайных значений, как любая другая локальная автоматическая переменная (и они часто реализуются с использованием автоматических переменных в стеке каждого потока). Возьмите эту простую программу в качестве примера:
#include <stdio.h>
#include <omp.h>
int main (void)
{
int i = 10;
#pragma omp parallel private(i)
{
printf("thread %d: i = %d\n", omp_get_thread_num(), i);
i = 1000 + omp_get_thread_num();
}
printf("i = %d\n", i);
return 0;
}
С четырьмя потоками он выводит что-то вроде:
thread 0: i = 0
thread 3: i = 32717
thread 1: i = 32717
thread 2: i = 1
i = 10
(another run of the same program)
thread 2: i = 1
thread 1: i = 1
thread 0: i = 0
thread 3: i = 32657
i = 10
Это ясно демонстрирует, что ценность i
является случайным (не инициализированным) внутри параллельной области, и что любые изменения в нем не видны после параллельной области (то есть переменная сохраняет свое значение до входа в область).
Если i
сделан firstprivate
затем он инициализируется значением, которое он имеет перед параллельной областью:
thread 2: i = 10
thread 0: i = 10
thread 3: i = 10
thread 1: i = 10
i = 10
Еще изменения в стоимости i
внутри параллельной области не видно после нее.
Вы уже знаете о lastprivate
(и это не применимо к простой демонстрационной программе, так как в ней отсутствуют конструкции с разделением рабочих мест).
Так да, firstprivate
а также lastprivate
это просто особые случаи private
, Первый из них приводит к переносу значений из внешнего контекста в параллельную область, а второй - к переносу значений из параллельного региона во внешний контекст. Логическое обоснование этих классов совместного использования данных заключается в том, что внутри параллельной области все частные переменные скрывают переменные из внешнего контекста, т.е. невозможно использовать операцию присваивания для изменения внешнего значения i
изнутри параллельной области.
firstprivate
а также lastprivate
это просто особые случаи private
,
Первый из них приводит к переносу значений из внешнего контекста в параллельную область, а второй - к переносу значений из параллельного региона во внешний контекст.
Вы не можете использовать локальную переменную
i
перед инициализацией программа выдаст ошибку начиная с C++ 14 Standard.