Кажется, что у вашего последовательного кода есть зависимость, которая делает его непригодным для параллельного выполнения. Предположим, что есть несколько значений i & j, которые делают «некоторое условие» истинным - тогда порядок выполнения циклов i & j do определяет, какое из этих условий будет найдено первым, и устанавливает значение результата, после которого возвращается Утверждение завершает поиск дополнительных случаев i, j, что «некоторое условие» является истинным. В последовательном коде циклы do всегда выполняются в одном и том же порядке, поэтому работа программы является детерминированной, и всегда будут обнаруживаться идентичные значения i & j, которые делают истинным «некоторое условие». В параллельной версии различные циклы я выполняю в недетерминированном порядке, так что от запуска к запуску различные значения i могут быть первым i-значением, которое находит истинное «некоторое условие».
Возможно, вы, как программист, знаете, что существует только одно значение i & j, которое приводит к истинному «некоторому условию»? В этом случае короткое замыкание казалось бы нормальным. Но спецификация OpenMP гласит: «Никакой оператор в связанных циклах, кроме операторов DO, не может вызвать переход
из циклов ", поэтому прерывание вывода во внутреннем цикле не допускается. Выходной цикл не допускается. Если это так, что всегда есть только одно истинное" некое условие ", вы можете просто удалить" возврат "и потерять ЦП время, когда потоки ищут «какое-то условие», истинно после того, как был найден один случай. Это может все же быть быстрее, чем последовательная программа. С переменной «result» масштабатора она все еще, вероятно, несовместима, имея зависимость от порядок выполнения. Вы можете изменить его на «уменьшение», суммирование результата или вернуть результат в виде 1-D массива измерения (n). Если вам нужно найти наименьшее значение i, которое имеет «некоторое условие» true Вы можете получить это из результата массива, используя встроенную функцию Fortran minloc.
Решение со многими директивами "сбросить" и "критично" не может быть быстрее, чем последовательная версия.
ОБНОВЛЕНИЕ: Основываясь на разъяснении, что возможны несколько результатов и что любой подойдет, один параллельный метод будет состоять в том, чтобы возвращать множественные результаты и позволять последовательному коду выбирать один - превращать «результат» в 1D массив, а не скалер. Вам разрешено закорачивать внутренний j-цикл, потому что он не «связан» с директивой «omp do», поэтому «результат» должен быть только 1D с размерами в соответствии с диапазоном i. Итак, как-то так:
program test1
integer :: i, j
integer, parameter :: n = 10
integer, dimension (n) :: result
result = -999
!omp parallel default (shared) private (i, j)
!omp do
do i = 1, n
inner: do j = i+1, n
if ( mod (i+j,14) == 0 ) then
result (i) = i
exit inner
end if
end do inner
end do
!omp end do
!omp end parallel
write (*, *) 'All results'
write (*, *) result
write (*, *)
write (*, *) 'One result'
write (*, *) result ( maxloc (result, 1) )
end program test1