Partilhar via


OpenMP Directives

Fornece links para diretivas usadas na API OpenMP.

Visual C++ suporta as seguintes diretivas OpenMP.

Para a partilha paralela do trabalho:

Directive Description
parallel Define uma região paralela, que é o código que será executado por vários threads em paralelo.
for Faz com que o trabalho feito em um for loop dentro de uma região paralela seja dividido entre threads.
sections Identifica as seções de código a serem divididas entre todos os threads.
single Permite especificar que uma seção de código deve ser executada em um único thread, não necessariamente no thread principal.

Para thread principal e sincronização:

Directive Description
master Especifica que somente o thread principal deve executar uma seção do programa.
critical Especifica que o código é executado apenas em um thread de cada vez.
barrier Sincroniza todos os threads em uma equipe; Todos os fios param na barreira, até que todos os fios executem a barreira.
atomic Especifica que um local de memória será atualizado atomicamente.
flush Especifica que todos os threads têm a mesma exibição de memória para todos os objetos compartilhados.
ordered Especifica que o código sob um loop paralelo for deve ser executado como um loop sequencial.

Para ambiente de dados:

Directive Description
threadprivate Especifica que uma variável é privada para um thread.

atómico

Especifica que um local de memória que será atualizado atomicamente.

#pragma omp atomic
   expression

Parameters

expression
A instrução que tem o lvalue, cujo local de memória você deseja proteger contra mais de uma gravação.

Remarks

A atomic diretiva não suporta cláusulas.

Para obter mais informações, consulte 2.6.4 Construção atômica.

Example

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

#define MAX 10

int main() {
   int count = 0;
   #pragma omp parallel num_threads(MAX)
   {
      #pragma omp atomic
      count++;
   }
   printf_s("Number of threads: %d\n", count);
}
Number of threads: 10

barrier

Sincroniza todos os threads em uma equipe; Todos os fios param na barreira, até que todos os fios executem a barreira.

#pragma omp barrier

Remarks

A barrier diretiva não suporta cláusulas.

Para mais informações, ver 2.6.3 Diretiva de barreira.

Example

Para obter um exemplo de como usar barriero , consulte mestre.

crítico

Especifica que o código só deve ser executado em um thread de cada vez.

#pragma omp critical [(name)]
{
   code_block
}

Parameters

name
(Opcional) Um nome para identificar o código crítico. O nome deve ser colocado entre parênteses.

Remarks

A critical diretiva não suporta cláusulas.

Para obter mais informações, consulte 2.6.2 construção crítica.

Example

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

#define SIZE 10

int main()
{
    int i;
    int max;
    int a[SIZE];

    for (i = 0; i < SIZE; i++)
    {
        a[i] = rand();
        printf_s("%d\n", a[i]);
    }

    max = a[0];
    #pragma omp parallel for num_threads(4)
        for (i = 1; i < SIZE; i++)
        {
            if (a[i] > max)
            {
                #pragma omp critical
                {
                    // compare a[i] and max again because max
                    // could have been changed by another thread after
                    // the comparison outside the critical section
                    if (a[i] > max)
                        max = a[i];
                }
            }
        }

    printf_s("max = %d\n", max);
}
41
18467
6334
26500
19169
15724
11478
29358
26962
24464
max = 29358

libertar espaço

Especifica que todos os threads têm a mesma exibição de memória para todos os objetos compartilhados.

#pragma omp flush [(var)]

Parameters

var
(Opcional) Uma lista separada por vírgulas de variáveis que representam objetos que você deseja sincronizar. Se var não for especificado, toda a memória será liberada.

Remarks

A flush diretiva não suporta cláusulas.

Para obter mais informações, consulte 2.6.5 diretiva flush.

Example

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

void read(int *data) {
   printf_s("read data\n");
   *data = 1;
}

void process(int *data) {
   printf_s("process data\n");
   (*data)++;
}

int main() {
   int data;
   int flag;

   flag = 0;

   #pragma omp parallel sections num_threads(2)
   {
      #pragma omp section
      {
         printf_s("Thread %d: ", omp_get_thread_num( ));
         read(&data);
         #pragma omp flush(data)
         flag = 1;
         #pragma omp flush(flag)
         // Do more work.
      }

      #pragma omp section
      {
         while (!flag) {
            #pragma omp flush(flag)
         }
         #pragma omp flush(data)

         printf_s("Thread %d: ", omp_get_thread_num( ));
         process(&data);
         printf_s("data = %d\n", data);
      }
   }
}
Thread 0: read data
Thread 1: process data
data = 2

for

Faz com que o trabalho feito em um for loop dentro de uma região paralela seja dividido entre threads.

#pragma omp [parallel] for [clauses]
   for_statement

Parameters

clauses
(Opcional) Zero ou mais cláusulas, consulte a secção Observações .

for_statement
Um for loop. O comportamento indefinido resultará se o código do for usuário no loop alterar a variável de índice.

Remarks

A for diretiva apoia as seguintes cláusulas:

Se parallel também for especificado, clauses pode ser qualquer cláusula aceita pelas parallelfor ou diretivas, exceto nowait.

Para obter mais informações, consulte 2.4.1 para construir.

Example

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

#define NUM_THREADS 4
#define NUM_START 1
#define NUM_END 10

int main() {
   int i, nRet = 0, nSum = 0, nStart = NUM_START, nEnd = NUM_END;
   int nThreads = 0, nTmp = nStart + nEnd;
   unsigned uTmp = (unsigned((abs(nStart - nEnd) + 1)) *
                               unsigned(abs(nTmp))) / 2;
   int nSumCalc = uTmp;

   if (nTmp < 0)
      nSumCalc = -nSumCalc;

   omp_set_num_threads(NUM_THREADS);

   #pragma omp parallel default(none) private(i) shared(nSum, nThreads, nStart, nEnd)
   {
      #pragma omp master
      nThreads = omp_get_num_threads();

      #pragma omp for
      for (i=nStart; i<=nEnd; ++i) {
            #pragma omp atomic
            nSum += i;
      }
   }

   if  (nThreads == NUM_THREADS) {
      printf_s("%d OpenMP threads were used.\n", NUM_THREADS);
      nRet = 0;
   }
   else {
      printf_s("Expected %d OpenMP threads, but %d were used.\n",
               NUM_THREADS, nThreads);
      nRet = 1;
   }

   if (nSum != nSumCalc) {
      printf_s("The sum of %d through %d should be %d, "
               "but %d was reported!\n",
               NUM_START, NUM_END, nSumCalc, nSum);
      nRet = 1;
   }
   else
      printf_s("The sum of %d through %d is %d\n",
               NUM_START, NUM_END, nSum);
}
4 OpenMP threads were used.
The sum of 1 through 10 is 55

master

Especifica que somente o thread principal deve executar uma seção do programa.

#pragma omp master
{
   code_block
}

Remarks

A master diretiva não suporta cláusulas.

Para obter mais informações, consulte 2.6.1 master construct.

Para especificar que uma seção de código deve ser executada em um único thread, não necessariamente o thread principal, use a diretiva única .

Example

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

int main( )
{
    int a[5], i;

    #pragma omp parallel
    {
        // Perform some computation.
        #pragma omp for
        for (i = 0; i < 5; i++)
            a[i] = i * i;

        // Print intermediate results.
        #pragma omp master
            for (i = 0; i < 5; i++)
                printf_s("a[%d] = %d\n", i, a[i]);

        // Wait.
        #pragma omp barrier

        // Continue with the computation.
        #pragma omp for
        for (i = 0; i < 5; i++)
            a[i] += i;
    }
}
a[0] = 0
a[1] = 1
a[2] = 4
a[3] = 9
a[4] = 16

ordered

Especifica que o código sob um loop paralelo for deve ser executado como um loop sequencial.

#pragma omp ordered
   structured-block

Remarks

A ordered diretiva deve estar dentro da extensão dinâmica de um pró ou parallel for construção com uma ordered cláusula.

A ordered diretiva não suporta cláusulas.

Para obter mais informações, consulte 2.6.6 construção ordenada.

Example

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

static float a[1000], b[1000], c[1000];

void test(int first, int last)
{
    #pragma omp for schedule(static) ordered
    for (int i = first; i <= last; ++i) {
        // Do something here.
        if (i % 2)
        {
            #pragma omp ordered
            printf_s("test() iteration %d\n", i);
        }
    }
}

void test2(int iter)
{
    #pragma omp ordered
    printf_s("test2() iteration %d\n", iter);
}

int main( )
{
    int i;
    #pragma omp parallel
    {
        test(1, 8);
        #pragma omp for ordered
        for (i = 0 ; i < 5 ; i++)
            test2(i);
    }
}
test() iteration 1
test() iteration 3
test() iteration 5
test() iteration 7
test2() iteration 0
test2() iteration 1
test2() iteration 2
test2() iteration 3
test2() iteration 4

parallel

Define uma região paralela, que é o código que será executado por vários threads em paralelo.

#pragma omp parallel [clauses]
{
   code_block
}

Parameters

clauses
(Opcional) Zero ou mais cláusulas, consulte a secção Observações .

Remarks

A parallel diretiva apoia as seguintes cláusulas:

parallel também pode ser usado com as diretivas para e seções .

Para obter mais informações, consulte 2.3 Construção paralela.

Example

O exemplo a seguir mostra como definir o número de threads e definir uma região paralela. O número de threads é igual por padrão ao número de processadores lógicos na máquina. Por exemplo, se você tiver uma máquina com um processador físico que tenha o hyperthreading habilitado, ela terá dois processadores lógicos e dois threads. A ordem de saída pode variar em diferentes máquinas.

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

int main() {
   #pragma omp parallel num_threads(4)
   {
      int i = omp_get_thread_num();
      printf_s("Hello from thread %d\n", i);
   }
}
Hello from thread 0
Hello from thread 1
Hello from thread 2
Hello from thread 3

sections

Identifica as seções de código a serem divididas entre todos os threads.

#pragma omp [parallel] sections [clauses]
{
   #pragma omp section
   {
      code_block
   }
}

Parameters

clauses
(Opcional) Zero ou mais cláusulas, consulte a secção Observações .

Remarks

A sections diretiva pode conter zero ou mais section diretivas.

A sections diretiva apoia as seguintes cláusulas:

Se parallel também for especificado, clauses pode ser qualquer cláusula aceita pelas parallelsections ou diretivas, exceto nowait.

Para obter mais informações, consulte 2.4.2 sections construct.

Example

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

int main() {
    #pragma omp parallel sections num_threads(4)
    {
        printf_s("Hello from thread %d\n", omp_get_thread_num());
        #pragma omp section
        printf_s("Hello from thread %d\n", omp_get_thread_num());
    }
}
Hello from thread 0
Hello from thread 0

single

Permite especificar que uma seção de código deve ser executada em um único thread, não necessariamente no thread principal.

#pragma omp single [clauses]
{
   code_block
}

Parameters

clauses
(Opcional) Zero ou mais cláusulas, consulte a secção Observações .

Remarks

A single diretiva apoia as seguintes cláusulas:

Para obter mais informações, consulte 2.4.3 construção única.

Para especificar que uma seção de código só deve ser executada no thread principal, use a diretiva master em vez disso.

Example

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

int main() {
   #pragma omp parallel num_threads(2)
   {
      #pragma omp single
      // Only a single thread can read the input.
      printf_s("read input\n");

      // Multiple threads in the team compute the results.
      printf_s("compute results\n");

      #pragma omp single
      // Only a single thread can write the output.
      printf_s("write output\n");
    }
}
read input
compute results
compute results
write output

threadprivate

Especifica que uma variável é privada para um thread.

#pragma omp threadprivate(var)

Parameters

var
Uma lista separada por vírgulas de variáveis que você deseja tornar privadas para um thread. var deve ser uma variável com escopo global ou de namespace ou uma variável estática local.

Remarks

A threadprivate diretiva não suporta cláusulas.

A threadprivate diretiva é baseada no atributo thread usando a palavra-chave threadprivate__declspec(thread) __declspec Por exemplo, uma threadprivate variável existirá em qualquer thread iniciado no processo, não apenas naqueles threads que fazem parte de uma equipe de thread gerada por uma região paralela. Esteja atento a este detalhe de implementação; Você pode notar que os construtores para um threadprivate tipo definido pelo usuário são chamados com mais frequência do que o esperado.

Você pode usar threadprivate em uma DLL que é carregada estaticamente na inicialização do processo, no entanto, você não pode usar threadprivate em qualquer DLL que será carregada via LoadLibrary , como DLLs que são carregadas com /DELAYLOAD (importação de carga de atraso), que também usa LoadLibrary.

Não é garantido que uma threadprivate variável de um tipo destrutível tenha seu destruidor chamado. For example:

struct MyType
{
    ~MyType();
};

MyType threaded_var;
#pragma omp threadprivate(threaded_var)
int main()
{
    #pragma omp parallel
    {}
}

Os usuários não têm controle sobre quando os threads que constituem a região paralela serão encerrados. Se esses threads existirem quando o processo for encerrado, os threads não serão notificados sobre a saída do processo e o destruidor não será chamado para threaded_var nenhum thread, exceto aquele que sair (aqui, o thread primário). Portanto, o código não deve contar com a destruição adequada de threadprivate variáveis.

Para obter mais informações, consulte 2.7.1 threadprivate directive.

Example

Para obter um exemplo de uso threadprivatedo , consulte private.