Sdílet prostřednictvím


2.7.2.6 reduction

Tato klauzule provádí snížení skalární proměnné, které se zobrazují v seznamu proměnné, s op operátor.Syntaxe reduction klauzule je takto:

reduction(op:variable-list)

Snížení obvykle určena pro výkaz s jedním z následujících formulářů:

x     =  x      op      expr 
x      binop=  expr 
x     =  expr      op      x            (except for subtraction)
x++
++x 
x--
--x

kde:

  • x
    Jeden snížení proměnných v list.

  • seznam proměnných
    Čárkami oddělený seznam snížení skalární proměnné.

  • výraz
    Výraz s skalární typ, který neobsahuje odkaz x.

  • op
    Není přetíženého operátoru, ale jeden z +, *, - &, ^, |, & &, nebo |.

  • binop
    Není přetíženého operátoru, ale jeden z +, *, - &, ^, nebo |.

Následuje příklad reduction klauzule:

#pragma omp parallel for reduction(+: a, y) reduction(||: am)
for (i=0; i<n; i++) {
   a += b[i];
   y = sum(y, c[i]);
   am = am || b[i] == c[i];
}

Jak je uvedeno v příkladu může být skrytý operátor dovnitř volání funkce.Uživatel je třeba dbát na to, že provozovatel podle reduction klauzule odpovídá snížení operace.

Přestože pravý operand || operátor nemá žádné vedlejší účinky v tomto příkladu, jsou povoleny, ale je třeba používat opatrně.V této souvislosti může dojít během spuštění paralelní, vedlejším účinkem, který je zaručeně nejsou během postupné provádění smyčky.Tento rozdíl může dojít, protože pořadí spouštění iterací je neurčitá.

Operátor používá určit počáteční hodnotu jakékoli soukromé proměnné kompilátor používá pro snižování a určit dokončení operátora.Určení provozovatele výslovně umožňuje snížení prohlášení mimo rozsah lexikální konstruktu.Libovolný počet reduction doložky mohou být specifikovány na směrnice, ale může se proměnná v nejvýše jednu reduction klauzule uvedené směrnice.

Soukromé kopii každé proměnné v seznamu proměnné je vytvořen, jeden pro každý podproces jako private klauzule byly použity.Soukromé kopie inicializován podle provozovatele (viz následující tabulka).

Na konci oblasti, pro které reduction byla zadána klauzule, původní objekt aktualizován výsledkem sloučení s konečné hodnoty každého soukromé kopie pomocí operátoru zadané původní hodnotu.Snížení operátory jsou asociativní všech (kromě pro odčítání) a kompilátor může volně opětovné přiřazení výpočtu konečné hodnoty.(Částečné výsledky snížení odečítání jsou přidány do formuláře konečné hodnoty.)

Při první podproces dosažení obsahující klauzuli a tak zůstane, dokud nebude výpočtu snížení stane neurčitý hodnotu původního objektu.Obvykle výpočtu bude dokončena na konci konstrukce; Pokud reduction na konstrukce, které je použita klauzule nowait je použito také původní objekt zůstává hodnota neurčitý před provedením synchronizace bariéry zajistit, že všechny podprocesy dokončili reduction klauzule.

Následující tabulka uvádí operátory, které jsou platné a jejich hodnoty kanonický inicializace.Inicializace skutečná hodnota bude konzistentní s typem dat snížení proměnné.

Operátor

Inicializace

+

0

*

1

-

0

&

~0

|

0

^

0

& &

1

||

0

Omezení týkající reduction klauzule jsou následující:

  • Typ proměnné v reduction klauzule musí být platné pro snížení operátor, typy ukazatele a referenční nikdy povoleno.

  • Proměnná, která je určena v reduction klauzule nesmí být const-kvalifikované.

  • Proměnné, které jsou v rámci regionu paralelní soukromé nebo které se zobrazí reduction klauzule paralelní směrnice nemůže být specifikován v reduction klauzule na směrnice sdílení práce, spojující paralelní konstrukce.

    #pragma omp parallel private(y)
    { /* ERROR - private variable y cannot be specified
                 in a reduction clause */
       #pragma omp for reduction(+: y)
       for (i=0; i<n; i++)
          y += b[i];
    }
    
    /* ERROR - variable x cannot be specified in both
               a shared and a reduction clause */
    #pragma omp parallel for shared(x) reduction(+: x)