Зачем инициализировать редукционную переменную вне параллельной конструкции?

Я изучаю, как портировать мой код Fortran в OpenMP. Когда я читаю онлайн-руководство (см. здесь) я наткнулся на один вопрос.

Во-первых, со страницы 28 я знал, что значение редукционной переменной не определено с момента, когда первый поток достигает предложения, и до завершения операции.

Насколько я понимаю, утверждение подразумевает, что не имеет значения, инициализирую ли я редукционную переменную до того, как программа попадет в параллельную конструкцию, потому что она не определена до завершения операции. Однако пример кода на странице 27 того же учебника инициализирует переменную сокращения перед параллельной конструкцией.

Подскажите, пожалуйста, какое лечение правильное? Спасибо.

Ли

sum = 0.0
!$omp parallel default(none) shared(n,x) private(i)
do i = 1, n
   sum = sum + x(i)
end do
!$omp end do
!$omp end parallel
print*, sum 

person Li-Pin Juan    schedule 10.04.2014    source источник
comment
Обратите внимание, что, хотя вы можете законно называть sum редукционной переменной в своем коде, она не является редукционной переменной OpenMP. В директиве parallel нет пункта reduction.   -  person High Performance Mark    schedule 10.04.2014


Ответы (2)


После исправления вашего кода:

integer,parameter :: n = 10000
real :: x(n)

x = 1

sum = 0
!$omp parallel do default(none) shared(x) private(i) reduction(+:sum)
do i = 1, n
   sum = sum + x(i)
end do
!$omp end parallel do
print*, sum 
end

Обратите внимание, что значение, которым вы инициализируете sum, имеет значение! Если вы измените его, вы получите другой результат. Совершенно очевидно, что вы должны правильно инициализировать его, и даже версия OpenMP плохо определена без надлежащей инициализации.

Да, значение суммы не определено до завершения цикла, но это не значит, что оно может быть неопределенным до цикла.

person Vladimir F    schedule 10.04.2014
comment
Спасибо за ответ. Еще один вопрос. В руководстве по OpenMP сказано, что инициализация, выполняемая оператором +, равна нулю. Если это так, то почему нам нужно беспокоиться о начальном значении, присвоенном сумме, прежде чем попасть в параллельную область? - person Li-Pin Juan; 10.04.2014
comment
Локальная копия каждой переменной списка создается и инициализируется в зависимости от «op» (например, 0 для «+»). – Компилятор находит стандартные выражения редукции, содержащие «op», и использует их для обновления локальной копии. – Локальные копии сводятся к одному значению и объединяются с исходным глобальным значением. - person Vladimir F; 10.04.2014
comment
Так что да, исходное начальное значение действительно имеет значение. - person Vladimir F; 10.04.2014

Во-первых, одной из замечательных особенностей OpenMP является то, что если вы скомпилируете программу без включения OpenMP, программа может/(должна!) также быть корректной последовательной программой. Последовательная версия вашего примера будет плохо определена без инициализации «суммы» перед циклом.

person janneb    schedule 10.04.2014
comment
Спасибо за ответ. Вы напомнили мне о какой-то базовой концепции, когда проверяли, не пойдет ли что-то не так при переходе от последовательной к параллельной программе. Еще один вопрос. В маунале OpenMP написано, что инициализация, которая идет с оператором +, равна нулю. Если это применимо к моему первоначальному вопросу, то зачем инициализировать переменную? Инструкция неправильная? - person Li-Pin Juan; 10.04.2014
comment
@isyegatech: чтобы повторить мой ответ, если вы компилируете без включения openmp, не имеет значения, что написано в руководстве по openmp, вам следует проверить руководство по fortran. - person janneb; 10.04.2014
comment
... и, как говорит Владимир Ф., есть разница между суммой глобальных переменных и локальными переменными для каждого потока. - person janneb; 10.04.2014