Região Critica: região critica, ou seção critica, é uma parte do código que acessa recursos compartilhados entre threads ou processos.
Condição de corrida: é a indesejável situação em que mais de uma operação ocorre ao mesmo tempo. Nesse caso, é quando duas ou mais threads acessam suas regiões críticas ao mesmo tempo.
Para resolver o problema da condição de corrida, é possível declarar as variáveis dentro de uma região paralela, fazendo com que cada thread tenha suas próprias variáveis, porém, há vezes em que essas variáveis precisam ser declaradas na região sequencial e acessadas por várias threads. Para resolver isso, existem as cláusulas, que são utilizadas em conjunto com as diretivas de compilação do OpenMP. As principais cláusulas estão listadas abaixo.
Sintaxe: shared(list)
Descrição: garante que as variáveis passadas no parâmetro sejam compartilhadas entre as threads, ou seja, se uma thread mudar o valor de uma variável compartilhada, todas as outras threads acessarão o valor modificado.
Sintaxe: private(list)
Descrição: garante que as variáveis passadas no parâmetro sejam privadas entre as threads, ou seja, cada thread tem variáveis com nomes iguais, porém, valores diferentes.
Sintaxe: firstprivate(list)
Descrição: garante que as variáveis passadas no parâmetro sejam privadas e, no começo do bloco de código paralelo, inicializa essas variáveis com o valor original delas.
Sintaxe: linear(linear-list[ : linear-step]). Onde linear-list pode ser: list, modifier(list) e modifier pode ser val.
Descrição: garante que os itens da lista serão privados e que tenham uma relação linear com o loop associado ao construct. Cada variável em cada iteração corresponde ao valor original da variável mais o número lógico da iteração vezes linear-step.
Sintaxe: copyin(list)
Descrição: copia o valor de cada variável threadprivate da thread principal para a variável threadprivate de cada thread da região paralela do construct atual.
Sintaxe: copyprivate(list)
Descrição: transmite um valor do ambiente de dados de uma tarefa implícita a outra tarefa implícita pertencente a região paralela.
Sintaxe: if(condição)
Descrição: se condição for true(verdadeira), a região é executada de forma paralela, se não, a região é executada de forma sequencial.
Sintaxe: set_threads(int num_threads)
Descrição: isso definirá o número de threads a serem utilizadas pelo bloco de código atual.
Sintaxe: default(shared) ou default(private)
Descrição: quando default(shared) definido, garante que todas as variáveis declaradas na região sequencial sejam compartilhada entre as threads, o que já é o padrão. Se default(private) for utilizado, garantirá que todas as variáveis declaradas na região sequencial sejam privadas entre as threads.
Nota: list é uma lista de itens(ou variáveis), tal como a, b, c, ... , sendo a, b e c variáveis declaradas na região sequencial.
Diretiva executável é um trecho de código que deve ser interpretado pelo compilador. Cada diretiva dessas começa com #pragma omp e deve ter um bloco de código na sequência. Uma construct é, basicamente, a junção de uma diretiva executável e o código associado a ela. Algumas das principais constructs estão listadas abaixo.
Sintaxe:
#pragma omp parallel [clause[ [, ]clause] ...]
bloco de código
Descrição: cria um time de threads que executam a região.
Sintaxe:
#pragma omp teams [clause[ [, ]clause] ...]
bloco de código
Descrição: cria um conjunto de times de threads, onde a thread principal de cada time executa a região.
Sintaxe:
#pragma omp sections
{
[#pragma omp section]
bloco de código
[#pragma omp section
bloco de código]
}
Descrição: contém um conjunto de blocos que são distribuídos e executados pelas threads no time
Sintaxe:
#pragma omp single [clause[ [, ]clause] ...]
bloco de código
Descrição: especifica que o bloco é executado apenas por uma das threads do time.
Sintaxe:
#pragma omp master
bloco de código
Descrição: especifica que o bloco deve ser executado pela thread principal do time (master thread, ou thread mestre).
Sintaxe:
#pragma omp for [clause[ [, ]clause] ...]
bloco de código(loops for)
Descrição: especifica que as iterações dos loops associados serão executadas em paralelo pelas threads do time.
Abaixo estão listadas algumas das principais funções(rotinas) da biblioteca do OpenMP.
Sintaxe: void omp_set_num_threads(int num_threads)
Descrição: define o número de threads que as seguintes regiões paralelas utilizarão.
Sintaxe: int omp_get_num_threads(void)
Descrição: retorna o número de threads da região paralela atual. Retorna 1 se chamada em uma região sequencial.
Sintaxe: int omp_get_max_threads(void)
Descrição: retorna o número máximo de threads que podem ser usadas em uma região paralela. Definido na variável de ambiente OMP_NUM_THREAD ou na função omp_set_num_threads.
Sintaxe: int omp_get_thread_num(void)
Descrição: retorna o número da thread que está sendo executada. Retorna 0 se chamada em uma região sequencial.
Sintaxe: int omp_get_num_procs(void)
Descrição: retorna o número de processadores disponíveis na máquina.
Sintaxe: int omp_in_parallel(void)
Descrição: retorna true(1) se chamada em uma região paralela. Retorna false(0) se chamada em uma região sequencial.
Sintaxe: void omp_set_dynamic(int dynamic_threads)
Descrição: habilita ou desabilita o ajuste dinâmico do número de threads disponíveis para as seguintes regiões paralelas. 0 desabilita, diferente de 0 habilita.
Sintaxe: int omp_get_dynamic(void)
Descrição: retorna true(1) se o ajuste dinâmico de threads está habilitado. Retorna false(0) caso contrário.
Sintaxe: int omp_get_thread_limit(void)
Descrição: retorna o número máximo de threads que podem ser utilizadas.
Nota: todo o conteúdo apresentado nessa página é destinado à linguagem C.