====== OpenMP in Fortran ======
OpenMP stellt eine einfache Möglichkeiten dar, Code zu parallelisieren. Dabei parallelisiert der Compiler automatisch Schleifen etc, mithilfe von mehreren Threads.
===== Parallel Do =====
Eine Do-Schleife (also eine Zählschleife) lässt sich durch OpenMP parallelisieren, wenn die Zählvariable im Schleifenkörper nicht verändert wird. Bspw. ist es möglich folgende Schleife zu parallelisieren:
program main
integer, parameter :: n = 1000000
integer :: k
integer,dimension(n) :: value
do k=1, n, +1
value(k) = k**k
enddo
write (*,*) (value(k), k=1, n)
end program
Hier werden also Quadratzahlen der Zahlen von 1 bis 1000000 berechnet. Nun geben wir dem Compiler zu verstehen, dass die do-Schleife parallel ausgeführt werden soll:
program main
integer, parameter :: n = 1000000
integer :: k
integer,dimension(n) :: value
!$omp parallel do
do k=1, n, +1
value(k) = k**k
enddo
!$omp end parallel do
write (*,*) (value(k), k=1, n)
end program
Übersetzen wir den Code:
gfortran do_omp.f90 -fopenmp
Und führen aus, erhalten wir folgende Zeiten:
$ gfortran do.f90
$ time ./a.out > /dev/null
real 0m0.303s
user 0m0.289s
sys 0m0.011s
$ gfortran do_omp.f90 -fopenmp
$ time ./a.out > /dev/null
real 0m0.288s
user 0m0.354s
sys 0m0.013s
Eine Einschätzung, warum der Geschwindigkeitsgewinn so gering sein könnten, finden Sie unten.
===== Reduktion =====
Neben vielen weiteren Funktionen von OpenMP gibt es noch die Möglichkeit eine Reduktion anzugeben, oder Variablen privat pro Thread oder shared zu setzen. Hier wird eine Summe über alle Quadratzahlen berechnet:
program main
integer, parameter :: n = 1000000
integer :: k
integer :: summe
!$omp parallel do reduction(+:summe) default(shared), private(k)
do k=1, n, +1
summe = summe + k**k
enddo
!$omp end parallel do
write (*,*) summe
end program
====== Warum sind die gezeigten Beispiele so langsam? ======
OpenMP arbeitet mit Threads, dh. aus dem Code, den Sie dem Compiler übergeben, erzeugt dieser Threads. Die Threaderzeugung benötigt eine Weile. Wenn also jeder Thread wenig Arbeit zu machen hat, dann überwiegt die Erzeugungszeit der Threads, gegenüber der Ersparnis der Berechnungszeit. Bei größeren Beispielen sollen Sie Laufzeitverringerungen bemerken.