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 van chunk op een round robin-manier. Als chunk 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 van chunk met een first-come-first-served beleid, totdat er geen batch meer overblijft. Indien niet gespecificeerd, wordt chunk ingesteld op 1
  • guided[,chunk] : als dynamic 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 de OMP_SCHEDULE van de omgevingsvariabele OMP_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.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow