OpenMP
-
Upload
valter-ferlete -
Category
Technology
-
view
111 -
download
0
description
Transcript of OpenMP
OpenMPValter Ferlete - [email protected]
Programação Multi-Core - T0111/09/2014
OpenMP● Origem;● Visão Geral;● Objetivos;● Prós e Contras;● Modelo de Memória e Execução;● Serviços OpenMP;● Variáveis de ambiente;● Diretivas e Cláusulas.
Origem● No início dos anos 90, fabricantes de máquinas com memória
compartilhada forneciam extensões para programação paralela em Fortran;
● As implementações permitiam ao usuário inserir diretivas para indicar onde loops deveriam ser paralelizados e os compiladores eram responsáveis pela paralelização;
● Implementações funcionalmente parecidas, mas não portáveis e começaram a divergir;
● ANSI X3H5 em 1994 foi a primeira tentativa de padronização.
Origem● A especificação padrão OpenMP começou em 1997 partindo
do padrão X3H5 graças ao aparecimento de novas arquiteturas de máquinas de memória compartilhada;
● Alguns parceiros na especificação:○ Compaq, HP, Intel, IBM, Silicon, Sun○ Absoft, GENIAS, Myrias, The Portland Group○ ANSYS, Dash, ILOG CPLEX, Livermore, NAG
● A API para Fortran foi liberada em Outubro de 1997 e para C/C++ no final de 1998.
Linha do tempo
Visão Geral● Biblioteca de mais alto nível para programação paralela;
● Prevê memória compartilhada;
● Requer suporte do compilador;
● Exige biblioteca específica com implementações thread safe.
OpenMP
Objetivos OpenMP
● Prover um padrão para uma variedade de plataformas e arquiteturas baseadas em memória compartilhada;
● Estabelecer um conjunto limitado e simples de diretivas para programação utilizando memória compartilhada;
● Prover capacidade para paralelizar um programa de forma incremental;
● Implementar paralelismo com granulosidade fina e grossa● Suportar Fortran, C e C++.
Por que usar OpenMP?
● Facilidade de conversão de programas sequênciais em
paralelos;
● Maneira simples de explorar paralelismo;
● Fácil compreensão e uso das diretivas;
● Minimiza a interferência na estrutura do algoritmo;
● Compila e executa em ambientes paralelos e sequencial.
Por que não usar OpenMP?
● Requer um compilador que suporta OpenMP;
● A escalabilidade é limitada pela arquitetura de memória;
● Manipulação segura do erro está em falta;
● Carece de mecanismo refinado para controlar o
mapeamento thread-processor.
Modelo de Memória
➔ Memória distribuída● Sistema computacional constituído de vários
processadores dotados de recursos individuais;
● Este sistema se caracteriza pela troca de mensagem entre os processadores;
● A troca de mensagem é feita por uma biblioteca de comunicação (MPI).
Modelo de programação baseado em MPI
Modelo de Memória
➔ Memória compartilhada● Sistema computacional constituído de vários
processadores que compartilham o mesmo recurso de memória;
● É necessário a sincronização do acesso aos dados na memória compartilhada pelos processadores.
OpenMP, Threads, Posix Threads
Thread Overview
Modelo de Execução Fork - Join
OpenMP usa o modelo fork-join para paralelizar a execuçãoFORK: A thread principal cria um grupo de threads paralelas;JOIN: Quando grupo threads completa a região paralela, ele sincroniza e finaliza, mantendo apenas a thread principal.
Organização do OpenMP
Serviços do OpenMP● Biblioteca de serviços
○ Permite controlar e interagir com o ambiente de execução.● Exemplos:
○ omp_get_thread_num()○ omp_set_num_threads(nthreads)○ omp_get _num_threads() ○ omp_set_num_threads()○ omp_get_max_threads()○ omp_set_nested()
Variáveis de ambiente➢ OMP_NUM_THREADS
○ Identifica o número de atividades que serão executadas em paralelo;○ (default: número de processadores).
➢ OMP_DYNAMIC○ Indica se o número de atividades a serem executadas em paralelo
deve ou não ser ajustado dinamicamente;○ (default:FALSE).
➢ OMP_NESTED○ Indica se deve ser contemplado ativação de paralelismo aninhado;○ (default: FALSE).
➢ OMP_SCHEDULE○ Define esquema de escalonamento das atividades paralelas.○ (default: estático).
Diretivas de compilação➢ A maioria dos construtores em OpenMP são diretivas do compilador ou pragmas;➢ Diretivas consiste em uma linha de código com significado “especial” para o
compilador;➢ Para C e C++, a diretiva possui a seguinte forma:
○ #pragma omp construct [clause [clause] …]○ Ex. #pragma omp parallel
➢ Para Fortran:○ !$OMP PARALLEL
➢ Pragma Parallel○ Define uma região paralelizável sobre um bloco estruturado de código;○ As threads bloqueiam no fim da região;○ Os dados são compartilhados (shared) entre as threads ao menos que seja
especificados de outra forma.
Um exemplo genérico#include <omp.h>main ( ){
//Código seqüencial (master)#pragma omp parallel{
// Código paralelo ….}
// Código seqüencial (master)
}
Região Paralela
Hello World#include <omp.h>#include <stdio.h>
int main() { int nthreads; omp_set_num_threads(4); // Configura o número de treads #pragma omp parallel{ printf("Hello World da thread %d\n", omp_get_thread_num()); if ( omp_get_thread_num() == 0 ) { nthreads = omp_get_num_threads(); printf("Existem %d threads\n",nthreads); } }// Final da Região Paralela return 0;}
Compilar e executarCompilar: $ gcc -o hello -fopenmp hello.c
Executar: $ export OMP_NUM_THREADS=2 (Opcional)$ .\helloc
Diretivas e Cláusulas● Diretivas
○ Construtor Paralelo#pragma omp parallel
○ Construtores de trabalho#pragma omp for#pragma omp single#pragma omp sections
○ Construtores de sincronização#pragma omp critical#pragma omp master#pragma omp atomic#pragma omp barrier#pragma omp flush#pragma omp ordered#pragma omp threadprivate
● CláusulasDefinem o comportamento das regiões e das variáveis aos quais estão associadas
sharedprivatefirstprivatelastprivatenum_threadsscheduledefault
orderedcopyncopyprivateifnowaitreduction
Diretiva / Construtor paralelo● parallel
○ Informa ao compilador a existência de uma região que deve ser executada em paralelo.
omp_set_num_threads(4);#pragma omp parallel{
int i;printf(“\n”);for( i = 0; i< 2; i++)
printf(“Iteração = %d\n”, i);}
Diretiva / Construtor paralelo● parallel Cláusula reduction
○ reduction(operador:variável), permite operar sobre o valor de uma variável;○ Cada execução pode manipular sua cópia, como em private;○ O valor local inicial é definido pela operação de redução;○ No final uma operação de redução atualiza o dados na thread master.
int soma=100;omp_set_num_threads(4);#pragma omp parallel reduction(+:soma){
soma +=1;}//No retorno ao master a soma=104
Diretiva / Construtor de trabalho● for / parallel for
○ Permite que os grupos de instruções definidas em um loop sejam paralelizadas.
float dot_prod(float* a, float* b, int N){float sum =0.0;#pragma omp parallel for shared(sum)for(int i=0;i<N;i++){
sum+=a[i]*b[i];}return sum;
}
Paralelismo aninhado● Dentro de uma região paralela, quando as threads encontram outro construtor
paralelo, elas criam novos grupos de threads e tornam-se as threads mestre desses novos grupos;
● Essas regiões são denominadas regiões paralelas aninhadas e por padrão são executadas de forma sequêncial, ou seja, o novo grupo criado contém apenas uma thread, que é a própria thread mestre do grupo.
#pragma omp parallel {#pragma omp parallel forfor( int i = 0; i < n; i++ ){
#pragma omp parallel forfor( int i = 0; i < n; i++ )
c[i] = a[i]+b[i];}
}
Diretiva / Construtor de trabalho● single
○ Indica que em uma região paralela ou um trecho de código deve ser executado apenas por uma única thread.
#pragma omp parallel num_threads(6){
#pragma omp singleprintf(“ler a entrada”);//somente uma thread lê entrada
printf(“calcular resultado”);//Várias threads calculam o resultado
#pragma omp singleprintf(“escreve na saida”); // somente uma thread escreve na saída
}
Diretiva / Construtor de trabalho● single [nowait]
○ com nowait a barreira pode ser relaxada.
#pragma omp parallel{
#pragma omp singleprintf(“Serão %d threads \n”, omp_get_num_threads())taskA();#pragma omp single nowaitprintf(“A thread %d terminou \n”, omp_get_thread_num());
}
Diretiva / Construtor de trabalho● sections
○ Cria seções paralelas;○ Cada seção será executada em uma thread diferente.
main (){int x=2;#pragma omp sections{
#pragma omp section{ taskA(x); }
#pragma omp section{ taskB(x); }
}}
Diretiva / Construtor de sincronização● critical[(nome)]
○ Permite que trechos de código sejam executados em regime de exclusão mútua.
int prox_x, prox_y;#pragma omp parallel shared(x,y) private (prox_x, prox_y){
#pragma omp critical(eixox)prox_x = dequeue(x);taskA(prox_x,x);
#pragma omp critical(eixoy)prox_y = dequeue(y);taskA(prox_y,y);
}
Diretiva / Construtor de sincronização● master [nowait]
○ Indica que em uma região paralela ou um trecho de código deve ser executado apenas pela thread master;
○ Representa uma barreira;○ com nowait a barreira pode ser relaxada.
#pragma omp parallel{
#pragma omp masterprintf(“Serão %d threads \n”, omp_get_num_threads());foo();#pragma omp master nowaitprintf(“A thread master terminou \n”);
}
Diretiva / Construtor de sincronização● atomic [read, write, update e capture]
Especifica que uma posição de memória deve ser atualizada atomicamente.#pragma omp atomic
● barrierQuando esta directiva é alcançada por uma thread, este espera até que os
restantes chegem ao mesmo ponto.#pragma omp barrier
● flushIdentifica um ponto de sincronização no qual é necessário providenciar uma
visão consistente memória.#pragma omp flush
Cláusula - Schedule● Cláusula: schedule
○ Afeta como as iterações do laço são mapeadas entre as threads○ schedule(static [,chunk])
■ Blocos de iterações de tamanho “chunk”■ Distribuição Round robin
○ schedule(dynamic [,chunk])■ Iteração de tamanho “chunk”■ Ao terminar as iterações, a thread requisita o próximo passo
○ schedule(guided [,chunk])■ Agendamento dinâmico iniciado com um tamanho grande■ O tamanho dos blocos diminui, não menor do que “chunk”
Cláusula - Schedule
Cláusula - Schedule● Cláusula: schedule (Exemplo)
#pragma omp parallel for schedule (static, 4) shared(qtdePrimos)for(i = 0; i < 500; i++){
if (testaPrimo(i) == 1){#pragma omp atomic
qtdePrimos++;}
}
$ export OMP_SCHEDULE=“static,4”
Cláusula - IF● Cláusula: if(expressão lógica)
○ Se a expressão lógica for verdadeira a região paralela será executada por mais de uma thread.
void test(int val){#pragma omp parallel if (val==2)if (omp_in_parallel()){
#pragma omp singleprintf("val = %d, paralelizado com %d threads\n", val,
omp_get_num_threads());}else { printf("val = %d, serializado\n", val);}
}
Saída:
val = 0, serializadoval = 1, serializadoval = 2, paralelizado com 2 threads
Chamando:
test(0);test(1);test(2);
Cláusula - Private
int i=10;#pragma omp parallel private(i){
printf("thread %d: i = %d\n", omp_get_thread_num(), i);i = 100 + omp_get_thread_num();
}printf("i = %d\n", i);
● Cláusula: private○ Especifica que cada thread deve ter sua própria instância de uma variável;○ A variável não é inicializada;○ Alterações de valor dentro da região paralela não são visíveis fora;○ Utilizando firstprivate ou lastprivate o valor de i é inicializado com o valor
antes do início da região paralela.
thread 0: i = 0thread 3: i = 0thread 1: i = 32696thread 2: i = 0i = 10
Mais sobre OpenMP● Site oficialhttp://openmp.org/● OpenMP Forumhttp://openmp.org/forum/● The Community of OpenMP Users, Researchers, Tool Developers and Providershttp://www.compunity.org/● C++ and OpenMPhttp://www.compunity.org/events/pastevents/parco07/parco_cpp_openmp.pdf● OpenMP C and C++ Application Program Interfacehttp://www.openmp.org/mp-documents/cspec20.pdf
Referênciashttps://computing.llnl.gov/tutorials/openMP
http://openmp.org/mp-documents/OpenMP4.0.0.Examples.pdf
http://www.cenapad.unicamp.br/servicos/treinamentos/apostilas/apostila_openmp.pdf