Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Esta seção descreve as funções da biblioteca de tempo de execução OpenMP C e C++. O cabeçalho <omp.h> declara dois tipos, várias funções que podem ser usadas para controlar e consultar o ambiente de execução paralela e funções de bloqueio que podem ser usadas para sincronizar o acesso aos dados.
O tipo omp_lock_t é um tipo de objeto capaz de representar que um bloqueio está disponível ou que um encadeamento possui um bloqueio. Estas fechaduras são referidas como fechaduras simples.
O tipo omp_nest_lock_t é um tipo de objeto capaz de representar ou que um bloqueio está disponível, ou tanto a identidade do thread que possui o bloqueio quanto uma contagem de aninhamento (descrita abaixo). Essas fechaduras são conhecidas como bloqueios encaixáveis.
As funções da biblioteca são funções externas com ligação "C".
As descrições neste capítulo estão divididas nos seguintes tópicos:
3.1 Funções do ambiente de execução
As funções descritas nesta seção afetam e monitoram threads, processadores e o ambiente paralelo:
- omp_set_num_threads
- omp_get_num_threads
- omp_get_max_threads
- omp_get_thread_num
- omp_get_num_procs
- omp_in_parallel
- omp_set_dynamic
- omp_get_dynamic
- omp_set_nested
- omp_get_nested
3.1.1 Função omp_set_num_threads
A omp_set_num_threads função define o número padrão de threads a serem usados para regiões paralelas posteriores que não especificam uma num_threads cláusula. O formato é o seguinte:
#include <omp.h>
void omp_set_num_threads(int num_threads);
O valor do parâmetro num_threads deve ser um número inteiro positivo. Seu efeito depende se o ajuste dinâmico do número de threads está habilitado. Para um conjunto abrangente de regras sobre a interação entre a função e o ajuste dinâmico de threads, consulte a omp_set_num_threadsseção 2.3.
Esta função tem os efeitos descritos acima quando chamada a partir de uma parte do programa onde a omp_in_parallel função retorna zero. Se for chamado a partir de uma parte do programa onde a omp_in_parallel função retorna um valor diferente de zero, o comportamento dessa função é indefinido.
Esta chamada tem precedência sobre a OMP_NUM_THREADS variável de ambiente. O valor padrão para o número de threads, que pode ser estabelecido chamando omp_set_num_threads ou definindo a variável de ambiente OMP_NUM_THREADS, pode ser claramente alternado numa única diretiva parallel ao especificar a cláusula num_threads.
Para obter mais informações, consulte omp_set_dynamic.
Referências cruzadas
- função omp_set_dynamic
- omp_get_dynamic função
- OMP_NUM_THREADS variável de ambiente
- Cláusula num_threads
3.1.2 Função omp_get_num_threads
A omp_get_num_threads função retorna o número de threads atualmente na equipe que executa a região paralela a partir da qual é chamada. O formato é o seguinte:
#include <omp.h>
int omp_get_num_threads(void);
A num_threads cláusula, a omp_set_num_threads função e a OMP_NUM_THREADS variável de ambiente controlam o número de threads em uma equipe.
Se o número de threads não tiver sido definido explicitamente pelo usuário, o padrão será definido pela implementação. Esta função liga-se à diretiva de inclusão parallel mais próxima. Se chamada de uma parte serial de um programa ou de uma região paralela aninhada serializada, essa função retorna 1.
Para obter mais informações, consulte omp_set_dynamic.
Referências cruzadas
3.1.3 Função omp_get_max_threads
A função omp_get_max_threads retorna um inteiro que é garantido ser, pelo menos, tão grande quanto o número de threads que seriam usados para formar uma equipa se uma região paralela sem uma cláusula num_threads fosse encontrada nesse ponto do código. O formato é o seguinte:
#include <omp.h>
int omp_get_max_threads(void);
O seguinte expressa um limite inferior no valor de omp_get_max_threads:
threads-usado-para-próxima-equipa<=
omp_get_max_threads
Observe que, se outra região paralela usar a num_threads cláusula para solicitar um número específico de threads, a garantia no limite inferior do resultado de omp_get_max_threads não será mais mantida.
O omp_get_max_threads valor de retorno da função pode ser usado para alocar dinamicamente armazenamento suficiente para todos os threads da equipe formada na próxima região paralela.
Referências cruzadas
3.1.4 Função omp_get_thread_num
A omp_get_thread_num função retorna o número do thread, dentro de sua equipe, do thread que executa a função. O número do thread está entre 0 e omp_get_num_threads()-1, inclusive. O thread mestre da equipe é o thread 0.
O formato é o seguinte:
#include <omp.h>
int omp_get_thread_num(void);
Se chamado de uma região serial, omp_get_thread_num retorna 0. Se chamada de dentro de uma região paralela aninhada que é serializada, essa função retorna 0.
Referências cruzadas
- função omp_get_num_threads
3.1.5 Função omp_get_num_procs
A omp_get_num_procs função retorna o número de processadores que estão disponíveis para o programa no momento em que a função é chamada. O formato é o seguinte:
#include <omp.h>
int omp_get_num_procs(void);
3.1.6 Função omp_in_parallel
A omp_in_parallel função retorna um valor diferente de zero se for chamada dentro da extensão dinâmica de uma região paralela executada em paralelo, caso contrário, ela retorna 0. O formato é o seguinte:
#include <omp.h>
int omp_in_parallel(void);
Essa função retorna um valor diferente de zero quando chamada de dentro de uma região executada em paralelo, incluindo regiões aninhadas que são serializadas.
3.1.7 Função omp_set_dynamic
A omp_set_dynamic função permite ou desativa o ajuste dinâmico do número de threads disponíveis para a execução de regiões paralelas. O formato é o seguinte:
#include <omp.h>
void omp_set_dynamic(int dynamic_threads);
Se dynamic_threads avaliar para um valor diferente de zero, o número de threads usados na execução de regiões paralelas futuras pode ser ajustado automaticamente pelo ambiente de execução para otimizar o uso dos recursos do sistema. Como consequência, o número de threads especificado pelo usuário é a contagem máxima de threads. O número de threads na equipa que executa uma região paralela permanece fixo durante a duração dessa região paralela e é relatado pela função omp_get_num_threads.
Se dynamic_threads avaliar 0, o ajuste dinâmico é desativado.
Esta função tem os efeitos descritos acima quando chamada a partir de uma parte do programa onde a omp_in_parallel função retorna zero. Se for chamado a partir de uma parte do programa onde a omp_in_parallel função retorna um valor diferente de zero, o comportamento dessa função é indefinido.
Uma chamada para omp_set_dynamic tem precedência sobre a OMP_DYNAMIC variável de ambiente.
O padrão para o ajuste dinâmico de threads é definido pela implementação. Como resultado, os códigos de usuário que dependem de um número específico de threads para a execução correta devem desabilitar explicitamente os threads dinâmicos. As implementações não são necessárias para fornecer a capacidade de ajustar dinamicamente o número de threads, mas são necessárias para fornecer a interface para suportar a portabilidade em todas as plataformas.
Específico da Microsoft
O apoio atual de omp_get_dynamic e omp_set_dynamic é o seguinte:
O parâmetro de entrada para omp_set_dynamic não afeta a política de threading e não altera o número de threads.
omp_get_num_threads sempre retorna o número definido pelo usuário, se estiver definido, ou o número de thread padrão. Na implementação atual da Microsoft, omp_set_dynamic(0) desativa o threading dinâmico para que o conjunto existente de threads possa ser reutilizado para a seguinte região paralela.
omp_set_dynamic(1) ativa o processo de threading dinâmico ao eliminar o conjunto atual de threads e criar um novo para a próxima região paralela. O número de threads no novo conjunto é o mesmo que o conjunto antigo e é baseado no valor de retorno de omp_get_num_threads. Portanto, para obter o melhor desempenho, use omp_set_dynamic(0) para reutilizar os threads existentes.
Referências cruzadas
3.1.8 Função omp_get_dynamic
A omp_get_dynamic função retorna um valor diferente de zero se o ajuste dinâmico de threads estiver habilitado e retorna 0 caso contrário. O formato é o seguinte:
#include <omp.h>
int omp_get_dynamic(void);
Se a implementação não implementar o ajuste dinâmico do número de threads, essa função sempre retornará 0. Para obter mais informações, consulte omp_set_dynamic.
Referências cruzadas
- Para obter uma descrição do ajuste dinâmico do thread, consulte omp_set_dynamic.
3.1.9 Função omp_set_nested
A omp_set_nested função habilita ou desabilita o paralelismo aninhado. O formato é o seguinte:
#include <omp.h>
void omp_set_nested(int nested);
Se aninhado for avaliado como 0, o paralelismo aninhado será desabilitado, que é o padrão, e as regiões paralelas aninhadas serão serializadas e executadas pelo thread atual. Caso contrário, o paralelismo aninhado está habilitado e as regiões paralelas aninhadas poderão usar threads adicionais para criar equipas aninhadas.
Esta função tem os efeitos descritos acima quando chamada a partir de uma parte do programa onde a omp_in_parallel função retorna zero. Se for chamado a partir de uma parte do programa onde a omp_in_parallel função retorna um valor diferente de zero, o comportamento dessa função é indefinido.
Esta chamada tem precedência sobre a OMP_NESTED variável de ambiente.
Quando o paralelismo aninhado é habilitado, o número de threads usados para executar regiões paralelas aninhadas é definido pela implementação. Como resultado, implementações compatíveis com OpenMP têm permissão para serializar regiões paralelas aninhadas mesmo quando o paralelismo aninhado está habilitado.
Referências cruzadas
3.1.10 Função omp_get_nested
A omp_get_nested função retorna um valor diferente de zero se o paralelismo aninhado estiver habilitado e 0 se estiver desabilitado. Para obter mais informações sobre paralelismo aninhado, consulte omp_set_nested. O formato é o seguinte:
#include <omp.h>
int omp_get_nested(void);
Se uma implementação não implementar paralelismo aninhado, essa função sempre retornará 0.
3.2 Funções de bloqueio
As funções descritas nesta seção manipulam bloqueios usados para sincronização.
Para as seguintes funções, a variável de bloqueio deve ter o tipo omp_lock_t. Esta variável só deve ser acedida através destas funções. Todas as funções de bloqueio requerem um argumento que contenha um ponteiro para o tipo omp_lock_t.
- A função omp_init_lock inicializa um bloqueio simples.
- A função omp_destroy_lock remove um bloqueio simples.
- A função omp_set_lock aguarda até que um bloqueio simples esteja disponível.
- A função omp_unset_lock libera um bloqueio simples.
- A função omp_test_lock testa um bloqueio simples.
Para as seguintes funções, a variável de bloqueio deve ter o tipo omp_nest_lock_t. Esta variável só deve ser acedida através destas funções. Todas as funções de bloqueio aninhadas requerem um argumento que tenha um ponteiro para omp_nest_lock_t digitar.
- A função omp_init_nest_lock inicializa um bloqueio aninhado.
- A função omp_destroy_nest_lock remove um bloqueio aninhado.
- A função omp_set_nest_lock aguarda até que um bloqueio aninhado esteja disponível.
- A função omp_unset_nest_lock libera um bloqueio aninhado.
- A função omp_test_nest_lock testa um bloqueio aninhado.
As funções de bloqueio OpenMP acessam a variável de bloqueio de tal forma que sempre leem e atualizam o valor mais atual da variável de bloqueio. Portanto, não é necessário que um programa OpenMP inclua diretivas explícitas flush para garantir que o valor da variável de bloqueio seja consistente entre diferentes threads. (Pode haver a necessidade flush de diretivas para tornar os valores de outras variáveis consistentes.)
3.2.1 Funções omp_init_lock e omp_init_nest_lock
Essas funções fornecem o único meio de inicializar um bloqueio. Cada função inicializa o bloqueio associado ao parâmetro bloqueio para uso em chamadas futuras. O formato é o seguinte:
#include <omp.h>
void omp_init_lock(omp_lock_t *lock);
void omp_init_nest_lock(omp_nest_lock_t *lock);
O estado inicial é desbloqueado (ou seja, nenhum thread possui o bloqueio). Para um bloqueio que permite aninhamento, a contagem inicial de aninhamento é zero. Não é compatível chamar qualquer uma dessas rotinas com uma variável de bloqueio que já foi inicializada.
3.2.2 Funções omp_destroy_lock e omp_destroy_nest_lock
Essas funções asseguram-se de que a variável de bloqueio lock não está inicializada. O formato é o seguinte:
#include <omp.h>
void omp_destroy_lock(omp_lock_t *lock);
void omp_destroy_nest_lock(omp_nest_lock_t *lock);
Não é compatível chamar qualquer uma dessas rotinas com uma variável de bloqueio não inicializada ou desbloqueada.
3.2.3 Funções omp_set_lock e omp_set_nest_lock
Cada uma dessas funções bloqueia o thread que executa a função até que o bloqueio especificado esteja disponível e, em seguida, define o bloqueio. Um cadeado simples está disponível se estiver desbloqueado. Um bloqueio aninhado estará disponível se estiver desbloqueado ou se já pertencer ao thread que executa a função. O formato é o seguinte:
#include <omp.h>
void omp_set_lock(omp_lock_t *lock);
void omp_set_nest_lock(omp_nest_lock_t *lock);
Para um bloqueio simples, o argumento para a omp_set_lock função deve apontar para uma variável de bloqueio inicializada. A propriedade do bloqueio é concedida ao thread que executa a função.
Para um bloqueio aninhado, o argumento para a função omp_set_nest_lock deve apontar para uma variável de bloqueio inicializada. A contagem de aninhamento é incrementada e o thread recebe ou mantém a propriedade do bloqueio.
3.2.4 Funções omp_unset_lock e omp_unset_nest_lock
Estas funções fornecem o meio de liberar a propriedade de uma fechadura. O formato é o seguinte:
#include <omp.h>
void omp_unset_lock(omp_lock_t *lock);
void omp_unset_nest_lock(omp_nest_lock_t *lock);
O argumento para cada uma dessas funções deve apontar para uma variável de bloqueio inicializada de propriedade do thread que executa a função. O comportamento será indefinido se o thread não possuir esse bloqueio.
Para um cadeado simples, a função omp_unset_lock liberta o fio de execução da posse do cadeado.
Para um bloqueio aninhado, a omp_unset_nest_lock função diminui a contagem de aninhamento e libera o thread que executa a função da propriedade do bloqueio se a contagem resultante for zero.
3.2.5 Funções omp_test_lock e omp_test_nest_lock
Essas funções tentam definir um bloqueio, mas não bloqueiam a execução do thread. O formato é o seguinte:
#include <omp.h>
int omp_test_lock(omp_lock_t *lock);
int omp_test_nest_lock(omp_nest_lock_t *lock);
O argumento deve apontar para uma variável de bloqueio inicializada. Essas funções tentam definir um bloqueio da mesma maneira que omp_set_lock e omp_set_nest_lock, exceto que elas não bloqueiam a execução do tópico.
Para um bloqueio simples, a omp_test_lock função retorna um valor diferente de zero se o bloqueio for definido com êxito, caso contrário, ele retorna zero.
Para um bloqueio aninhado, a função omp_test_nest_lock retorna a nova contagem de aninhamento se o bloqueio for definido com êxito; caso contrário, retorna zero.
3.3 Rotinas de cronometragem
As funções descritas nesta seção suportam um temporizador de relógio de parede portátil:
- A função omp_get_wtime retorna o tempo de relógio de parede decorrido.
- A função omp_get_wtick retorna o número de segundos entre sucessivos ticks de relógio.
3.3.1 Função omp_get_wtime
A omp_get_wtime função retorna um valor de ponto flutuante de precisão dupla igual ao tempo de relógio de parede decorrido em segundos desde algum "tempo no passado". O "tempo no passado" real é arbitrário, mas é garantido que não mudará durante a execução do programa de aplicação. O formato é o seguinte:
#include <omp.h>
double omp_get_wtime(void);
Prevê-se que a função seja usada para medir os tempos decorridos, conforme mostrado no exemplo a seguir:
double start;
double end;
start = omp_get_wtime();
... work to be timed ...
end = omp_get_wtime();
printf_s("Work took %f sec. time.\n", end-start);
Os tempos retornados são "tempos por thread", o que significa que eles não precisam ser globalmente consistentes em todos os threads que participam de um aplicativo.
3.3.2 Função omp_get_wtick
A omp_get_wtick função retorna um valor de ponto flutuante de precisão dupla igual ao número de segundos entre ticks de relógio sucessivos. O formato é o seguinte:
#include <omp.h>
double omp_get_wtick(void);