Partilhar via


Cláusulas OpenMP

Fornece ligações para as cláusulas usadas na API OpenMP.

O Visual C++ suporta as seguintes cláusulas OpenMP.

Para atributos gerais:

Cláusula Description
if Especifica se um ciclo deve ser executado em paralelo ou em série.
num_threads Define o número de threads numa equipa de threads.
encomendado Exigido numa instrução paralela for se uma diretiva ordenada for usada no ciclo.
Horário Aplica-se à diretiva FOR .
Nowait Sobrepõe-se à barreira implícita numa diretiva.

Para atributos de partilha de dados:

Cláusula Description
privado Especifica que cada thread deve ter a sua própria instância de uma variável.
firstprivate Especifica que cada thread deve ter a sua própria instância de uma variável, e que a variável deve ser inicializada com o valor da variável, porque existe antes do construto paralelo.
Lastprivate Especifica que a versão da variável no contexto envolvente é definida igual à versão privada da thread que executa a última iteração (construção do loop for) ou o último bloco (#pragma sections).
compartilhou Especifica que uma ou mais variáveis devem ser partilhadas entre todos os threads.
default Especifica o comportamento de variáveis não definidas numa região paralela.
redução Especifica que uma ou mais variáveis privadas de cada thread são sujeitas a uma operação de redução no final da região paralela.
Copiar para Permite que as threads acedam ao valor da thread principal, para uma variável threadprivate .
copyprivate Especifica que uma ou mais variáveis devem ser partilhadas entre todos os threads.

copyin

Permite que as threads acedam ao valor da thread principal, para uma variável threadprivate .

copyin(var)

Parâmetros

VAR
A threadprivate variável que será inicializada com o valor da variável no thread principal, tal como existe antes do construto paralelo.

Observações

copyin Aplica-se às seguintes diretivas:

Para mais informações, consulte 2.7.2.7 copyin.

Example

Veja threadprivate para um exemplo de utilização copyinde .

copyprivate

Especifica que uma ou mais variáveis devem ser partilhadas entre todos os threads.

copyprivate(var)

Parâmetros

VAR
Uma ou mais variáveis para partilhar. Se for especificada mais do que uma variável, separe os nomes das variáveis com uma vírgula.

Observações

copyprivate Aplica-se à diretiva única.

Para mais informações, consulte 2.7.2.8 copyprivate.

Example

// omp_copyprivate.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>

float x, y, fGlobal = 1.0;
#pragma omp threadprivate(x, y)

float get_float() {
   fGlobal += 0.001;
   return fGlobal;
}

void use_float(float f, int t) {
   printf_s("Value = %f, thread = %d\n", f, t);
}

void CopyPrivate(float a, float b) {
   #pragma omp single copyprivate(a, b, x, y)
   {
      a = get_float();
      b = get_float();
      x = get_float();
      y = get_float();
    }

   use_float(a, omp_get_thread_num());
   use_float(b, omp_get_thread_num());
   use_float(x, omp_get_thread_num());
   use_float(y, omp_get_thread_num());
}

int main() {
   float a = 9.99, b = 123.456;

   printf_s("call CopyPrivate from a single thread\n");
   CopyPrivate(9.99, 123.456);

   printf_s("call CopyPrivate from a parallel region\n");
   #pragma omp parallel
   {
      CopyPrivate(a, b);
   }
}
call CopyPrivate from a single thread
Value = 1.001000, thread = 0
Value = 1.002000, thread = 0
Value = 1.003000, thread = 0
Value = 1.004000, thread = 0
call CopyPrivate from a parallel region
Value = 1.005000, thread = 0
Value = 1.005000, thread = 1
Value = 1.006000, thread = 0
Value = 1.006000, thread = 1
Value = 1.007000, thread = 0
Value = 1.007000, thread = 1
Value = 1.008000, thread = 0
Value = 1.008000, thread = 1

predefinição

Especifica o comportamento de variáveis não definidas numa região paralela.

default(shared | none)

Observações

shared, que está em vigor se a default cláusula não for especificada, significa que qualquer variável numa região paralela será tratada como se fosse especificada com a cláusula partilhada . none significa que quaisquer variáveis usadas numa região paralela que não estejam com o âmbito das cláusulas private, shared, reduction, firstprivate ou lastprivate causarão um erro do compilador.

default Aplica-se às seguintes diretivas:

Para mais informações, consulte o padrão 2.7.2.5.

Example

Veja privado para um exemplo de utilização de default.

firstprivate

Especifica que cada thread deve ter a sua própria instância de uma variável, e que a variável deve ser inicializada com o valor da variável, porque existe antes do construto paralelo.

firstprivate(var)

Parâmetros

VAR
A variável terá instâncias em cada thread e será inicializada com o seu valor porque ela existe antes do construto paralelo. Se for especificada mais do que uma variável, separe os nomes das variáveis com uma vírgula.

Observações

firstprivate Aplica-se às seguintes diretivas:

Para mais informações, consulte 2.7.2.2 firstprivate.

Example

Para um exemplo de utilização do firstprivate, veja o exemplo em privado.

if (OpenMP)

Especifica se um ciclo deve ser executado em paralelo ou em série.

if(expression)

Parâmetros

expressão
Uma expressão integral que, se for avaliada como verdadeira (não nula), faz com que o código na região paralela seja executado em paralelo. Se a expressão for avaliada como falsa (zero), a região paralela é executada em série (por um único thread).

Observações

if Aplica-se às seguintes diretivas:

Para mais informações, veja construto paralelo 2.3.

Example

// omp_if.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>

void test(int val)
{
    #pragma omp parallel if (val)
    if (omp_in_parallel())
    {
        #pragma omp single
        printf_s("val = %d, parallelized with %d threads\n",
                 val, omp_get_num_threads());
    }
    else
    {
        printf_s("val = %d, serialized\n", val);
    }
}

int main( )
{
    omp_set_num_threads(2);
    test(0);
    test(2);
}
val = 0, serialized
val = 2, parallelized with 2 threads

lastprivate

Especifica que a versão da variável no contexto envolvente é definida igual à versão privada da thread que executa a última iteração (construção do loop for) ou o último bloco (#pragma sections).

lastprivate(var)

Parâmetros

VAR
A variável que é definida igual à versão privada do thread que executa a iteração final (construção for-loop) ou a última secção (#pragma secções).

Observações

lastprivate Aplica-se às seguintes diretivas:

Para mais informações, consulte 2.7.2.3 lastprivate.

Example

Ver schedule para um exemplo de utilização lastprivate da cláusula.

nowait

Sobrepõe-se à barreira implícita numa diretiva.

nowait

Observações

nowait Aplica-se às seguintes diretivas:

Para mais informações, veja 2.4.1 para construção, 2.4.2 construção de secções e 2.4.3 construção única.

Example

// omp_nowait.cpp
// compile with: /openmp /c
#include <stdio.h>

#define SIZE 5

void test(int *a, int *b, int *c, int size)
{
    int i;
    #pragma omp parallel
    {
        #pragma omp for nowait
        for (i = 0; i < size; i++)
            b[i] = a[i] * a[i];

        #pragma omp for nowait
        for (i = 0; i < size; i++)
            c[i] = a[i]/2;
    }
}

int main( )
{
    int a[SIZE], b[SIZE], c[SIZE];
    int i;

    for (i=0; i<SIZE; i++)
        a[i] = i;

    test(a,b,c, SIZE);

    for (i=0; i<SIZE; i++)
        printf_s("%d, %d, %d\n", a[i], b[i], c[i]);
}
0, 0, 0
1, 1, 0
2, 4, 1
3, 9, 1
4, 16, 2

num_threads

Define o número de threads numa equipa de threads.

num_threads(num)

Parâmetros

Num
O número de fios

Observações

A num_threads cláusula tem a mesma funcionalidade que a função omp_set_num_threads .

num_threads Aplica-se às seguintes diretivas:

Para mais informações, veja construto paralelo 2.3.

Example

Veja paralelo para um exemplo de utilização num_threads da cláusula.

encomendado

Exigido numa instrução paralela for se uma diretiva ordenada for usada no ciclo.

ordered

Observações

ordered Aplica-se à diretiva FOR.

Para mais informações, veja 2.4.1 para o constructo.

Example

Ver ordenado para ver um exemplo de como usar ordered cláusula.

privado

Especifica que cada thread deve ter a sua própria instância de uma variável.

private(var)

Parâmetros

VAR
A variável que possui instâncias em cada thread.

Observações

private Aplica-se às seguintes diretivas:

Para mais informações, consulte 2.7.2.1 privado.

Example

// openmp_private.c
// compile with: /openmp
#include <windows.h>
#include <assert.h>
#include <stdio.h>
#include <omp.h>

#define NUM_THREADS 4
#define SLEEP_THREAD 1
#define NUM_LOOPS 2

enum Types {
   ThreadPrivate,
   Private,
   FirstPrivate,
   LastPrivate,
   Shared,
   MAX_TYPES
};

int nSave[NUM_THREADS][MAX_TYPES][NUM_LOOPS] = {{0}};
int nThreadPrivate;

#pragma omp threadprivate(nThreadPrivate)
#pragma warning(disable:4700)

int main() {
   int nPrivate = NUM_THREADS;
   int nFirstPrivate = NUM_THREADS;
   int nLastPrivate = NUM_THREADS;
   int nShared = NUM_THREADS;
   int nRet = 0;
   int i;
   int j;
   int nLoop = 0;

   nThreadPrivate = NUM_THREADS;
   printf_s("These are the variables before entry "
           "into the parallel region.\n");
   printf_s("nThreadPrivate = %d\n", nThreadPrivate);
   printf_s("      nPrivate = %d\n", nPrivate);
   printf_s(" nFirstPrivate = %d\n", nFirstPrivate);
   printf_s("  nLastPrivate = %d\n", nLastPrivate);
   printf_s("       nShared = %d\n\n", nShared);
   omp_set_num_threads(NUM_THREADS);

   #pragma omp parallel copyin(nThreadPrivate) private(nPrivate) shared(nShared) firstprivate(nFirstPrivate)
   {
      #pragma omp for schedule(static) lastprivate(nLastPrivate)
      for (i = 0 ; i < NUM_THREADS ; ++i) {
         for (j = 0 ; j < NUM_LOOPS ; ++j) {
            int nThread = omp_get_thread_num();
            assert(nThread < NUM_THREADS);

            if (nThread == SLEEP_THREAD)
               Sleep(100);
            nSave[nThread][ThreadPrivate][j] = nThreadPrivate;
            nSave[nThread][Private][j] = nPrivate;
            nSave[nThread][Shared][j] = nShared;
            nSave[nThread][FirstPrivate][j] = nFirstPrivate;
            nSave[nThread][LastPrivate][j] = nLastPrivate;
            nThreadPrivate = nThread;
            nPrivate = nThread;
            nShared = nThread;
            nLastPrivate = nThread;
            --nFirstPrivate;
         }
      }
   }

   for (i = 0 ; i < NUM_LOOPS ; ++i) {
      for (j = 0 ; j < NUM_THREADS ; ++j) {
         printf_s("These are the variables at entry of "
                  "loop %d of thread %d.\n", i + 1, j);
         printf_s("nThreadPrivate = %d\n",
                  nSave[j][ThreadPrivate][i]);
         printf_s("      nPrivate = %d\n",
                  nSave[j][Private][i]);
         printf_s(" nFirstPrivate = %d\n",
                  nSave[j][FirstPrivate][i]);
         printf_s("  nLastPrivate = %d\n",
                  nSave[j][LastPrivate][i]);
         printf_s("       nShared = %d\n\n",
                  nSave[j][Shared][i]);
      }
   }

   printf_s("These are the variables after exit from "
            "the parallel region.\n");
   printf_s("nThreadPrivate = %d (The last value in the "
            "main thread)\n", nThreadPrivate);
   printf_s("      nPrivate = %d (The value prior to "
            "entering parallel region)\n", nPrivate);
   printf_s(" nFirstPrivate = %d (The value prior to "
            "entering parallel region)\n", nFirstPrivate);
   printf_s("  nLastPrivate = %d (The value from the "
            "last iteration of the loop)\n", nLastPrivate);
   printf_s("       nShared = %d (The value assigned, "
            "from the delayed thread, %d)\n\n",
            nShared, SLEEP_THREAD);
}
These are the variables before entry into the parallel region.
nThreadPrivate = 4
      nPrivate = 4
nFirstPrivate = 4
  nLastPrivate = 4
       nShared = 4

These are the variables at entry of loop 1 of thread 0.
nThreadPrivate = 4
      nPrivate = 1310720
nFirstPrivate = 4
  nLastPrivate = 1245104
       nShared = 3

These are the variables at entry of loop 1 of thread 1.
nThreadPrivate = 4
      nPrivate = 4488
nFirstPrivate = 4
  nLastPrivate = 19748
       nShared = 0

These are the variables at entry of loop 1 of thread 2.
nThreadPrivate = 4
      nPrivate = -132514848
nFirstPrivate = 4
  nLastPrivate = -513199792
       nShared = 4

These are the variables at entry of loop 1 of thread 3.
nThreadPrivate = 4
      nPrivate = 1206
nFirstPrivate = 4
  nLastPrivate = 1204
       nShared = 2

These are the variables at entry of loop 2 of thread 0.
nThreadPrivate = 0
      nPrivate = 0
nFirstPrivate = 3
  nLastPrivate = 0
       nShared = 0

These are the variables at entry of loop 2 of thread 1.
nThreadPrivate = 1
      nPrivate = 1
nFirstPrivate = 3
  nLastPrivate = 1
       nShared = 1

These are the variables at entry of loop 2 of thread 2.
nThreadPrivate = 2
      nPrivate = 2
nFirstPrivate = 3
  nLastPrivate = 2
       nShared = 2

These are the variables at entry of loop 2 of thread 3.
nThreadPrivate = 3
      nPrivate = 3
nFirstPrivate = 3
  nLastPrivate = 3
       nShared = 3

These are the variables after exit from the parallel region.
nThreadPrivate = 0 (The last value in the main thread)
      nPrivate = 4 (The value prior to entering parallel region)
nFirstPrivate = 4 (The value prior to entering parallel region)
  nLastPrivate = 3 (The value from the last iteration of the loop)
       nShared = 1 (The value assigned, from the delayed thread, 1)

Redução

Especifica que uma ou mais variáveis privadas de cada thread são sujeitas a uma operação de redução no final da região paralela.

reduction(operation:var)

Parâmetros

Funcionamento
O operador para a operação a ser realizada nas variáveis var ao final da região paralela.

VAR
Uma ou mais variáveis para fazer redução escalar. Se for especificada mais do que uma variável, separe os nomes das variáveis com uma vírgula.

Observações

reduction Aplica-se às seguintes diretivas:

Para mais informações, veja 2.7.2.6 redução.

Example

// omp_reduction.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>

#define NUM_THREADS 4
#define SUM_START   1
#define SUM_END     10
#define FUNC_RETS   {1, 1, 1, 1, 1}

int bRets[5] = FUNC_RETS;
int nSumCalc = ((SUM_START + SUM_END) * (SUM_END - SUM_START + 1)) / 2;

int func1( ) {return bRets[0];}
int func2( ) {return bRets[1];}
int func3( ) {return bRets[2];}
int func4( ) {return bRets[3];}
int func5( ) {return bRets[4];}

int main( )
{
    int nRet = 0,
        nCount = 0,
        nSum = 0,
        i,
        bSucceed = 1;

    omp_set_num_threads(NUM_THREADS);

    #pragma omp parallel reduction(+ : nCount)
    {
        nCount += 1;

        #pragma omp for reduction(+ : nSum)
        for (i = SUM_START ; i <= SUM_END ; ++i)
            nSum += i;

        #pragma omp sections reduction(&& : bSucceed)
        {
            #pragma omp section
            {
                bSucceed = bSucceed && func1( );
            }

            #pragma omp section
            {
                bSucceed = bSucceed && func2( );
            }

            #pragma omp section
            {
                bSucceed = bSucceed && func3( );
            }

            #pragma omp section
            {
                bSucceed = bSucceed && func4( );
            }

            #pragma omp section
            {
                bSucceed = bSucceed && func5( );
            }
        }
    }

    printf_s("The parallel section was executed %d times "
             "in parallel.\n", nCount);
    printf_s("The sum of the consecutive integers from "
             "%d to %d, is %d\n", 1, 10, nSum);

    if (bSucceed)
        printf_s("All of the functions, func1 through "
                 "func5 succeeded!\n");
    else
        printf_s("One or more of the functions, func1 "
                 "through func5 failed!\n");

    if (nCount != NUM_THREADS)
    {
        printf_s("ERROR: For %d threads, %d were counted!\n",
                 NUM_THREADS, nCount);
        nRet |= 0x1;
   }

    if (nSum != nSumCalc)
    {
        printf_s("ERROR: The sum of %d through %d should be %d, "
                "but %d was reported!\n",
                SUM_START, SUM_END, nSumCalc, nSum);
        nRet |= 0x10;
    }

    if (bSucceed != (bRets[0] && bRets[1] &&
                     bRets[2] && bRets[3] && bRets[4]))
    {
        printf_s("ERROR: The sum of %d through %d should be %d, "
                 "but %d was reported!\n",
                 SUM_START, SUM_END, nSumCalc, nSum);
        nRet |= 0x100;
    }
}
The parallel section was executed 4 times in parallel.
The sum of the consecutive integers from 1 to 10, is 55
All of the functions, func1 through func5 succeeded!

cronograma

Aplica-se à diretiva FOR .

schedule(type[,size])

Parâmetros

type
O tipo de agendamento, ou dynamic, guided, runtime, ou static.

tamanho
(Opcional) Especifica o tamanho das iterações. O tamanho deve ser um número inteiro. Não é válido quando o tipo é runtime.

Observações

Para mais informações, veja 2.4.1 para o constructo.

Example

// omp_schedule.cpp
// compile with: /openmp
#include <windows.h>
#include <stdio.h>
#include <omp.h>

#define NUM_THREADS 4
#define STATIC_CHUNK 5
#define DYNAMIC_CHUNK 5
#define NUM_LOOPS 20
#define SLEEP_EVERY_N 3

int main( )
{
    int nStatic1[NUM_LOOPS],
        nStaticN[NUM_LOOPS];
    int nDynamic1[NUM_LOOPS],
        nDynamicN[NUM_LOOPS];
    int nGuided[NUM_LOOPS];

    omp_set_num_threads(NUM_THREADS);

    #pragma omp parallel
    {
        #pragma omp for schedule(static, 1)
        for (int i = 0 ; i < NUM_LOOPS ; ++i)
        {
            if ((i % SLEEP_EVERY_N) == 0)
                Sleep(0);
            nStatic1[i] = omp_get_thread_num( );
        }

        #pragma omp for schedule(static, STATIC_CHUNK)
        for (int i = 0 ; i < NUM_LOOPS ; ++i)
        {
            if ((i % SLEEP_EVERY_N) == 0)
                Sleep(0);
            nStaticN[i] = omp_get_thread_num( );
        }

        #pragma omp for schedule(dynamic, 1)
        for (int i = 0 ; i < NUM_LOOPS ; ++i)
        {
            if ((i % SLEEP_EVERY_N) == 0)
                Sleep(0);
            nDynamic1[i] = omp_get_thread_num( );
        }

        #pragma omp for schedule(dynamic, DYNAMIC_CHUNK)
        for (int i = 0 ; i < NUM_LOOPS ; ++i)
        {
            if ((i % SLEEP_EVERY_N) == 0)
                Sleep(0);
            nDynamicN[i] = omp_get_thread_num( );
        }

        #pragma omp for schedule(guided)
        for (int i = 0 ; i < NUM_LOOPS ; ++i)
        {
            if ((i % SLEEP_EVERY_N) == 0)
                Sleep(0);
            nGuided[i] = omp_get_thread_num( );
        }
    }

    printf_s("------------------------------------------------\n");
    printf_s("| static | static | dynamic | dynamic | guided |\n");
    printf_s("|    1   |    %d   |    1    |    %d    |        |\n",
             STATIC_CHUNK, DYNAMIC_CHUNK);
    printf_s("------------------------------------------------\n");

    for (int i=0; i<NUM_LOOPS; ++i)
    {
        printf_s("|    %d   |    %d   |    %d    |    %d    |"
                 "    %d   |\n",
                 nStatic1[i], nStaticN[i],
                 nDynamic1[i], nDynamicN[i], nGuided[i]);
    }

    printf_s("------------------------------------------------\n");
}
------------------------------------------------
| static | static | dynamic | dynamic | guided |
|    1   |    5   |    1    |    5    |        |
------------------------------------------------
|    0   |    0   |    0    |    2    |    1   |
|    1   |    0   |    3    |    2    |    1   |
|    2   |    0   |    3    |    2    |    1   |
|    3   |    0   |    3    |    2    |    1   |
|    0   |    0   |    2    |    2    |    1   |
|    1   |    1   |    2    |    3    |    3   |
|    2   |    1   |    2    |    3    |    3   |
|    3   |    1   |    0    |    3    |    3   |
|    0   |    1   |    0    |    3    |    3   |
|    1   |    1   |    0    |    3    |    2   |
|    2   |    2   |    1    |    0    |    2   |
|    3   |    2   |    1    |    0    |    2   |
|    0   |    2   |    1    |    0    |    3   |
|    1   |    2   |    2    |    0    |    3   |
|    2   |    2   |    2    |    0    |    0   |
|    3   |    3   |    2    |    1    |    0   |
|    0   |    3   |    3    |    1    |    1   |
|    1   |    3   |    3    |    1    |    1   |
|    2   |    3   |    3    |    1    |    1   |
|    3   |    3   |    0    |    1    |    3   |
------------------------------------------------

partilhada

Especifica que uma ou mais variáveis devem ser partilhadas entre todos os threads.

shared(var)

Parâmetros

VAR
Uma ou mais variáveis para partilhar. Se for especificada mais do que uma variável, separe os nomes das variáveis com uma vírgula.

Observações

Outra forma de partilhar variáveis entre threads é através da cláusula copyprivate .

shared Aplica-se às seguintes diretivas:

Para mais informações, consulte 2.7.2.4 partilhado.

Example

Veja privado para um exemplo de utilização de shared.