Дипломная работа: Система автоматизации распараллеливания Отображение на SMP-кластер
!$OMP END DO
!$OMP END PARALLEL
CDVM$ PARALLEL (i,j) ON a(i,j),
*DVM$* REDUCTION (SUM(s))
do i=1,N
!$OMP PARALLEL PRIVATE(i, j)
!$OMP*REDUCTION(+: s)
!$OMP DO SCHEDULE (STATIC)
do j=1,M
S = S + A(I, J)
enddo
!$OMP END DO
!$OMP END PARALLEL
enddo
Клауза REDUCTION(+: s) означает, что каждая нить создаст в своей локальной памяти редукционную переменную, и будет накапливать в ней суммы элементов массива. По окончанию цикла эти локальные редукционные переменные нитей будут просуммированы и записаны в локальную редукционную переменную узла.
В варианте 3.1 локальные редукционные переменные нитей будут суммироваться по окончании внешнего цикла. В варианте 3.2 локальные редукционные переменные нитей суммируются на каждой итерации внешнего цикла, и это снова дополнительные накладные расходы.
Пример 4
Рассмотрим пример с регулярной зависимостью:
CDVM$ PARALLEL (i,j) ON a(i,j),
*DVM$* ACROSS (a(1:1,1:1))
do i=2,N-1
do j=2,M-1
A(I, J) = A(I-1, J) + A(I+1, J)
* + A(I, J-1) + A(I, J+1)
enddo
enddo
Тело данного цикла примечательно тем, что невозможно независимое выполнение витков цикла, т.к. прежде чем вычислить A(I, J), необходимо вычислить A(I-1, J) и A(I, J-1).
Прежде всего, клауза ACROSS (a(1:1,1:1)) определяет точное местоположение удаленных данных (теневые грани). Также ACROSS обеспечивает сохранение порядка вычислений витков цикла.
Для распараллеливания на OpenMP циклов с регулярной зависимостью используется алгоритм конвейерного выполнения при помощи синхронизующего массива. Этот алгоритм применялся в тестах NAS [12]. Цикл с регулярной зависимостью должен содержать тесно-вложенный цикл. Вариант распараллеливания здесь всего один: