1 / 29

Introdução ao OpenMP

Introdução ao OpenMP. Prof. André Leon S. Gradvohl , Dr . gradvohl@ft.unicamp.br. Arquiteturas paralelas. Arquiteturas paralelas: Single Instruction Multiple Data Máquinas Vetoriais Multiple Instruction Multiple Data Memória distribuída Memória compartilhada.

idana
Download Presentation

Introdução ao OpenMP

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Introdução ao OpenMP Prof. André Leon S. Gradvohl, Dr. gradvohl@ft.unicamp.br

  2. Arquiteturas paralelas • Arquiteturas paralelas: • Single Instruction Multiple Data • Máquinas Vetoriais • Multiple Instruction Multiple Data • Memória distribuída • Memória compartilhada Onde o OpenMP se encaixa

  3. Modelos de Programação paralela • Modelos de Programação Paralela • Multiprocessamento • Fork/Join • Passagem de Mensagens • Exemplo: PVM, MPI • Multithread • Exemplo: OpenMP, POSIX-Threads • OpenMP (Open MultiProcessing): • Interface de programação que suporta multiprocessamento em ambientes de memória compartilhada.

  4. Introdução ao OpenMP • Estrutura de um programa OpenMP: • Em Fortran: PROGRAM HELLO INTEGER VAR1, VAR2, VAR3 *** Código serial *** Início da seção paralela. “Fork” um grupo de “threads”. !$OMP PARALLEL PRIVATE(VAR1, VAR2) SHARED(VAR3) *** Seção paralela executada por todas as “threads” *** Todas as “threads” efetuam um “join” a thread mestre e finalizam !$OMP END PARALLEL *** Código serial END

  5. Introdução ao OpenMP • Estrutura de um programa OpenMP: • Em C: #include <omp.h> intmain () { int var1, var2, var3; *** Código serial *** Início da seção paralela. “Fork” um grupo de “threads”. #pragma omp parallel private(var1, var2) shared(var3) { *** Seção paralela executada por todas as “threads” *** Todas as “threads” efetuam um “join” a thread mestre e finalizam } *** Código serial }

  6. Introdução ao OpenMP • Observações • Fork/Join: • Quando uma thread chega a uma definição de região paralela, ela cria um conjunto de threads e passa a ser a thread mestre. A thread mestre faz parte do conjunto de threads e possui o número de identificação “0”. • A partir do início da região paralela, o código é duplicado e todas as threads executarão esse código. • Existe um ponto de sincronização (“barreira”) no final da região paralela, sincronizando o fim de execução de cada thread. Somente a thread mestre continua desse ponto. B A RR

  7. Introdução ao OpenMP • Observações • O número de threads • Em uma execução com o OpenMP, o número de “threads” é determinado pelos seguintes fatores, em ordem de precedência: • Utilização da função omp_set_num_threads() no código Fortran ou C/C++; • Definindo a variável de ambiente OMP_NUM_THREADS, antes da execução; • Implementação padrão do ambiente: número de processadores em um nó. • Restrições • Não é permitido caminhar para dentro ou fora (”branch”) de uma estrutura de blocos definida por uma diretiva OpenMP e somente um IF é permitido.

  8. Exemplo Faz o fork dos threads e mantém suas próprias cópias de variáveis. Obtém o número do Thread. Região Paralela #include <stdio.h> #include <omp.h> intmain () { intnthreads, tid; #pragma omp parallel private(nthreads, tid) { tid = omp_get_thread_num(); printf(“Ola Mundo do thread = %d\n”, tid); if (tid == 0) { nthreads = omp_get_num_threads(); printf(“Numero de threads = %d\n”, nthreads); } } } Se tid == 0, então é o thread mestre. Obtém a quantidade de threads.

  9. Criação de Threads Criação de 4 threads. • #include <stdio.h> • #include <omp.h> • int main() • { • double A[1000]; • #pragma omp parallel num_threads(4) • { • int ID = omp_get_thread_num(); • pooh(ID,A); • } • return 0; • } Obtém o número do thread.

  10. Criação de Threads – Exercícios • Matematicamente sabe-se que: • Portanto, é possívelaproximaresta integral como um somatório: • Ondecadaretângulo tem largurax e altura F(xi) no meio do intervalo i.

  11. Criação de Threads – Exercícios • Solução Serial: • static long num_steps = 100000; • double step; • int main () • { • int i; double x, pi, sum = 0.0; • step = 1.0/(double) num_steps; • for (i=0;i< num_steps; i++){ • x = (i+0.5)*step; • sum = sum + 4.0/(1.0+x*x); • } • pi = step * sum; • }

  12. Criação de Threads – Exercícios • Solução Paralela • static long num_steps = 100000000; • double step; • int main () • { • inti,j; • double pi, full_sum = 0.0; • double sum[MAX_THREADS]; • step = 1.0/(double) num_steps;

  13. Criação de Threads – Exercícios • omp_set_num_threads(MAX_THREADS); • full_sum=0.0; • #pragma omp parallel • { • int i; • int id = omp_get_thread_num(); • intnumthreads = omp_get_num_threads(); • double x; • sum[id] = 0.0; • if (id == 0) printf(" num_threads = %d",numthreads); • for (i=id;i< num_steps; i+=numthreads){ • x = (i+0.5)*step; • sum[id] = sum[id] + 4.0/(1.0+x*x); • } • } Região Paralela

  14. Criação de Threads – Exercícios • for(full_sum = 0.0, i=0;i< MAX_THREADS;i++) • full_sum += sum[i]; • pi = step * full_sum; • } Agrupamento dos resultados. (Redução)

  15. Diretiva DO/for Define uma região paralela • A diretiva DO/for especifica que as iterações de um laço sejam distribuídas e executadas em paralelo pelo grupo de threads. A região paralela tem que ter sido identificada antes. • Com isso, o programador não precisa de preocupar com a divisão da carga de trabalho entre os threads • Exemplo: #pragma omp parallel { #pragma omp for for (I=0;I<N;I++) Faca_algo(I); } O comando for será dividido igualmente entre os threads. Detalhe:a variável I é privativa.

  16. Diretiva DO/for • Alternativamente, pode-se utilizar a seguinte sintaxe: • Exemplo: #pragma omp parallel for for (I=0;I<N;I++) Faca_algo(I); Cuidado com o uso de outras variáveis dento de um “laço paralelo”!! As variáveis do laço são privativas de cada thread. • Exemplo: • int i, j, A[MAX]; • j = 5; • for (i=0;i< MAX; i++) { • j = j+ 2*i; • A[i] = big(j); • }

  17. Diretiva DO/for - Redução • Como resolver o caso ao lado? double ave=0.0, A[MAX]; int i; for (i=0;i< MAX; i++) { ave + = A[i]; } ave = ave/MAX; Resposta: usando uma redução ! double ave=0.0, A[MAX]; int i; #pragma omp parallel for reduction (+:ave) for (i=0;i< MAX; i++) { ave + = A[i]; } ave = ave/MAX;

  18. Diretiva DO/for – Redução – mais detalhes • Dentro de umaregiãoparalela: • É feitaumacópia local de cadavariável e inicializada com um valor quedepende do tipo de operação, e. g., naoperação de + o valor inicial é zero. • As cópiaslocaissãoreduzidas (somadas, multiplicadasetc) em um único valor que, posteriormente, sãocombinadosemumaúnicavariávelcomum. • Como fica o programaparacalcular o  com a diretiva for e a redução?

  19. Diretiva DO/for – Redução – mais detalhes • Solução Paralela • static long num_steps = 100000000; • double step; • int main () • { • inti,j; • double x, pi, sum = 0.0; • double sum[MAX_THREADS]; • step = 1.0/(double) num_steps;

  20. Diretiva DO/for – Redução – mais detalhes • omp_set_num_threads(MAX_THREADS); sum=0.0; • #pragma omp parallel for reduction (+:sum) • for (i=1;i< num_steps; i++){ • x = (i-0.5)*step; • sum= sum + 4.0/(1.0+x*x); • } • pi = step * sum; • } RegiãoParalela com redução

  21. Atributos de variáveis • As variáveis no OpenMP podem ser compartilhadas ou não entre os threads. Esse controle é feito através de alguns atributos. São eles: • private: Declara que as variáveis listadas serão de uso específico de cada “thread”. Essas variáveis não são iniciadas. • shared (default) Declara que as variáveis listadas compartilharão o seu conteúdo com todas as threads de um grupo. As variáveis existem em apenas um endereço de memória, que pode ser lido e escrito por todas as threads do grupo.

  22. Atributos de variáveis • firstprivate: Define uma lista de variáveis com o atributo PRIVATE, mas sendo inicializadas automaticamente, de acordo com o valor que possuíam no thread antes de uma região paralela. • lastprivate: Define uma lista de variáveis com o atributo PRIVATE e copia o valor da última iteração de um laço da última thread que finalizou. • default: Permite que o programador defina o atributo “default” para as variáveis em uma região paralela (PRIVATE, SHARED ou NONE).

  23. Atributos de variáveis exemplos Cada thread possui sua própria cópia da variável tmp com o valor inicial zero. • void useless() { • inttmp = 0; • #pragma ompparallel for firstprivate(tmp) • for (int j = 0; j < 1000; ++j) • tmp += j; • printf(“%d\n”, tmp); • }

  24. Atributos de variáveis exemplos • void useless() { • inttmp = 0; • #pragma ompparallelfor firstprivate(tmp) lastprivate(tmp) • for (int j = 0; j < 1000; ++j) • tmp += j; • printf(“%d\n”, tmp); • } A variável tmp termina com o valor do calculado pelo último thread a terminar.

  25. Seções • A diretiva sections divide o trabalho de forma não iterativa em seções separadas, aonde cada seção será executada por uma “thread” do grupo. Representa a implementação de paralelismo funcional, ou seja, por código. • Algumas observações: • A diretiva sections define a seção do código sequencial onde será definida as seções independentes, através da diretiva section; • Cada sectioné executada por uma thread do grupo; • Existe um ponto de sincronização implícita no final da diretiva section, a menos que se especifique o atributo nowait; • Se existirem mais threads do que seções, o OpenMP decidirá, quais threads executarão os blocos de section, e quais, não executarão.

  26. Seções- Exemplo Definição de uma área de seções. • #include <omp.h> • #define N 1000 • int main () { • int i, n=N; • float a[N], b[N], c[N]; • for (i=0; i < N; i++) a[i] = b[i] = i * 1.0; • #pragma omp parallel shared(a,b,c,n) private(i) { • #pragma omp sections nowait { • #pragma omp section • for (i=0; i < n/2; i++) • c[i] = a[i] + b[i]; • #pragma omp section • for (i=n/2; i < n; i++) • c[i] = a[i] + b[i]; • } /* fimseções*/ • } /* fim parallel */ • } Primeira seção Segunda seção

  27. Unicidade • A diretiva single determina que o código identificado seja executado por somente uma thread do grupo. • Os threads do grupo que não executam a diretiva single, esperam o fim do processamento da thread que executa a diretiva, a menos que se especifique o atributo nowait. • A diretiva ordered determina que as iterações do laço na região paralela, sejam executados na ordem sequêncial.

  28. Unicidade- Exemplos Apenas um thread vai executar esse trecho de código. Detalhe: nesse caso todos os threads aguardarão até que o bloco single seja executado. • #pragmaomp parallel • { • do_many_things(); • #pragmaomp single • { • exchange_boundaries(); • } • do_many_other_things(); • }

  29. Unicidade- Exemplos • #pragma omp parallel private (tmp) • #pragma omp for ordered reduction(+:res) • for (I=0;I<N;I++){ • tmp = NEAT_STUFF(I); • #pragma ordered • res += consum(tmp); • } Os threads executarão os trechos de código um de cada vez, de forma sequencial.

More Related