Хотя недостаток ассоциативности арифметики с плавающей запятой может быть проблемой в некоторых случаях, код, который вы здесь показывает, представляет гораздо более существенную проблему, которую вам необходимо решить в первую очередь: состояние переменной var
во внешнем цикле.
Действительно, поскольку var
изменяется внутри цикла i
, даже если только в j
части цикла i
, его необходимо как-то "приватизировать".Теперь точный статус, который нужно получить, зависит от значения, которое вы ожидаете сохранить при выходе из parallel
региона:
- Если вам не важно его значение, просто объявитеэто
private
(или лучше, объявите его внутри области parallel
. - Если вам нужно его окончательное значение в конце цикла
i
, и, учитывая, что оно накапливает сумму значений, скорее всего,вам нужно будет объявить это reduction(+:)
, хотя lastprivate
также может быть тем, что вы хотите (невозможно сказать без дополнительных подробностей) - Если
private
или lastprivate
- это все, что вам нужно, но выТакже необходимо указать его начальное значение при входе в область parallel
, тогда вам придется подумать и о добавлении firstprivate
(в этом нет необходимости, если вы выбрали reduction
, поскольку об этом уже позаботились)
Этого должно быть достаточно для исправления вашей проблемы.
Теперь в своем фрагменте вы также распараллелили внутренний цикл. Обычно это плохая идея, чтобы использовать вложенный параллелизм.очень веская причина дляТаким образом, вы, вероятно, получите намного лучшую производительность, только распараллеливая внешний цикл и оставляя внутренний цикл в покое.Это не будет означать, что внутренний цикл не выиграет от распараллеливания, а скорее, что несколько экземпляров внутреннего цикла будут вычисляться параллельно (каждый из которых, по общему признанию, является последовательным, но весь процесс параллелен).Приятным побочным эффектом удаления распараллеливания внутреннего цикла (в дополнение к ускорению работы кода) является то, что теперь все накопления внутри переменных var
Privates выполняются в том же порядке, что и не параллельно.Следовательно, ваши (гипотетические) арифметические проблемы с плавающей точкой во внешнем цикле теперь исчезнут, и только если вам понадобится окончательное уменьшение при выходе из области parallel
, вы все равно можете столкнуться с ними там.