openmp
Lusparallellisme in OpenMP
Zoeken…
parameters
Clausule | Parameter |
---|---|
private | Door komma's gescheiden lijst van privévariabelen |
firstprivate | Net als private , maar geïnitialiseerd op de waarde van de variabele voordat de lus wordt ingevoerd |
lastprivate | Net als private , maar de variabele krijgt de waarde die overeenkomt met de laatste iteratie van de lus bij het afsluiten |
reduction | reductie-operator : komma's gescheiden lijst van overeenkomstige reductievariabelen |
schedule | static , dynamic , guided , auto of runtime met een optionele brokgrootte na een coma voor de 3 voormalige |
collapse | Aantal perfect geneste lussen die samenvallen en parallel lopen |
ordered | Vertelt dat sommige delen van de lus op volgorde moeten worden gehouden (deze delen worden specifiek geïdentificeerd met enkele ordered clausules in de lus) |
nowait | Verwijder de impliciete barrière die standaard aan het einde van de lusconstructie bestaat |
Opmerkingen
De betekenis van de schedule
is als volgt:
-
static[,chunk]
: statisch verdelen (wat betekent dat de distributie wordt uitgevoerd voordat de lus wordt ingevoerd) de lusiteraties in batch vanchunk
op een round robin-manier. Alschunk
niet is opgegeven, zijn de chunks zo gelijk mogelijk en krijgt elke thread er maximaal één. -
dynamic[,chunk]
: verdeel de lusiteraties over de threads door batches vanchunk
met een first-come-first-served beleid, totdat er geen batch meer overblijft. Indien niet gespecificeerd, wordtchunk
ingesteld op 1 -
guided[,chunk]
: alsdynamic
maar met batches welke maten kleiner en kleiner worden, tot 1 -
auto
: laat de compiler en / of run time library beslissen wat het meest geschikt is -
runtime
: stel de beslissing tijdens runtime vast aan deOMP_SCHEDULE
van de omgevingsvariabeleOMP_SCHEDULE
. Als tijdens runtime de omgevingsvariabele niet is gedefinieerd, wordt de standaardplanning gebruikt
De standaard voor schedule
is implementatie definiëren . In veel omgevingen is het static
, maar het kan ook dynamic
of heel goed auto
. Zorg er daarom voor dat uw implementatie er niet impliciet op vertrouwt zonder deze expliciet in te stellen.
In de bovenstaande voorbeelden hebben we de samengevoegde vorm parallel for
of parallel do
. De lusconstructie kan echter worden gebruikt zonder deze te versmelten met de parallel
richtlijn, in de vorm van een #pragma omp for [...]
of !$omp do [...]
zelfstandige richtlijn binnen een parallel
gebied.
Alleen voor de Fortran-versie is (zijn) de lusindexvariabele (n) van de parallelle lus (sen) standaard altijd private
. Het is daarom niet nodig om ze expliciet private
verklaren (hoewel dit geen fout is).
Voor de C- en C ++ -versie zijn de lusindexen net als alle andere variabelen. Daarom, als hun reikwijdte zich buiten de parallelle lus (sen) uitstrekt (wat betekent dat als ze niet worden gedeclareerd als for ( int i = ...)
maar eerder als int i; ... for ( i = ... )
dan moeten private
worden verklaard.
Typisch voorbeeld in C
#include <stdio.h>
#include <math.h>
#include <omp.h>
#define N 1000000
int main() {
double sum = 0;
double tbegin = omp_get_wtime();
#pragma omp parallel for reduction( +: sum )
for ( int i = 0; i < N; i++ ) {
sum += cos( i );
}
double wtime = omp_get_wtime() - tbegin;
printf( "Computing %d cosines and summing them with %d threads took %fs\n",
N, omp_get_max_threads(), wtime );
return sum;
}
In dit voorbeeld berekenen we gewoon 1 miljoen cosinus en tellen we hun waarden parallel. We timen de uitvoering ook om te zien of de parallellisatie enig effect heeft op de prestaties. Omdat we de tijd meten, moeten we ervoor zorgen dat de compiler het werk dat we hebben gedaan niet zal optimaliseren, dus doen we alsof we het resultaat gebruiken door het gewoon terug te sturen.
Hetzelfde voorbeeld in Fortran
program typical_loop
use omp_lib
implicit none
integer, parameter :: N = 1000000, kd = kind( 1.d0 )
real( kind = kd ) :: sum, tbegin, wtime
integer :: i
sum = 0
tbegin = omp_get_wtime()
!$omp parallel do reduction( +: sum )
do i = 1, N
sum = sum + cos( 1.d0 * i )
end do
!$omp end parallel do
wtime = omp_get_wtime() - tbegin
print "( 'Computing ', i7, ' cosines and summing them with ', i2, &
& ' threads took ', f6.4,'s' )", N, omp_get_max_threads(), wtime
if ( sum > N ) then
print *, "we only pretend using sum"
end if
end program typical_loop
Ook hier berekenen en verzamelen we 1 miljoen cosinus. We timen de lus en om ongewenste optimalisatie van de compiler te voorkomen, doen we alsof we het resultaat gebruiken.
Voorbeelden compileren en uitvoeren
Op een 8-cores Linux-machine met GCC-versie 4.4 kunnen de C-codes worden samengesteld en op de volgende manier worden uitgevoerd:
$ gcc -std=c99 -O3 -fopenmp loop.c -o loopc -lm
$ OMP_NUM_THREADS=1 ./loopc
Computing 1000000 cosines and summing them with 1 threads took 0.095832s
$ OMP_NUM_THREADS=2 ./loopc
Computing 1000000 cosines and summing them with 2 threads took 0.047637s
$ OMP_NUM_THREADS=4 ./loopc
Computing 1000000 cosines and summing them with 4 threads took 0.024498s
$ OMP_NUM_THREADS=8 ./loopc
Computing 1000000 cosines and summing them with 8 threads took 0.011785s
Voor de Fortran-versie geeft het:
$ gfortran -O3 -fopenmp loop.f90 -o loopf
$ OMP_NUM_THREADS=1 ./loopf
Computing 1000000 cosines and summing them with 1 threads took 0.0915s
$ OMP_NUM_THREADS=2 ./loopf
Computing 1000000 cosines and summing them with 2 threads took 0.0472s
$ OMP_NUM_THREADS=4 ./loopf
Computing 1000000 cosines and summing them with 4 threads took 0.0236s
$ OMP_NUM_THREADS=8 ./loopf
Computing 1000000 cosines and summing them with 8 threads took 0.0118s
Toevoeging van twee vectoren met behulp van OpenMP parallel voor construct
void parallelAddition (unsigned N, const double *A, const double *B, double *C)
{
unsigned i;
#pragma omp parallel for shared (A,B,C,N) private(i) schedule(static)
for (i = 0; i < N; ++i)
{
C[i] = A[i] + B[i];
}
}
Dit voorbeeld voegt twee vectoren ( A
en B
aan C
) door een team threads te spawnen (bijvoorbeeld opgegeven door de OMP_NUM_THREADS
OMP_NUM_THREADS) en elke thread een stuk werk toe te wijzen (in dit voorbeeld statisch toegewezen via het schedule(static)
uitdrukking).
Zie opmerkingen met betrekking tot de private(i)
optie.