O documento fornece uma introdução ao OpenMP, descrevendo o que é OpenMP, suas vantagens, como funciona, diretivas principais e como compilar e executar um programa OpenMP.
1. API OpenMP (Introdução à Linguagem)
Autor: Ângelo Polotto – Aluno de Iniciação
Científica
Professor orientador: Rafael Frigori Bertolini
2. Introdução:
O que é o OPENMP?
O Openmp é uma Interface de Programação (API)
que permite de forma rápida, simples e padroniza a
divisão de um programa em multiplos processos
paralelos (threading) com memória compartilhada.
3.
Por que usar o OPENMP?
A possibilidade de dividir um processo qualquer
sem se preocupar com implementações
matemáticas e numéricas são pontos chaves para
a escolha do OPEMMP.
4. Diferenças entre o OPENMP e o
MPI
No MPI temos as seguintes considerações
para implementar um código:
Como ele será dividido?
Qual a função de cada computador
dependendo da posição no ranking?
Qual a forma mais eficiente de dividir o código
Em qual parte o código se divide?
Em qual parte o código se junta?
5.
Já no Openmp, temos as seguintes
preocupações possíveis para o mesmo
problema:
Quais partes do código serão divididas?
Em qual parte o código se divide?
Em qual parte o código se junta?
6. O que o OPENMP é capaz?
Abaixo está uma lista das vantagens do
OpenMP:
Padronização dos códigos
Grande portabilidade entre compiladores
Facilita o trabalho do programador por preservar o
uso de uma lógica sequêncial
Despreocupação com a troca de menssagens entre
os processos
7. O que o OPENMP não é capaz?
Apesar de parecer, o OpenMp não é capaz de
dividir os processos sozinho, além de não
saber como administrar as variáveis entre os
processos paralelos.
8. Plataformas
O OpenMp abrange uma grande variedade de
plataformas, tando de 32 e 64 bits, além
processadores com multiplos núcleos. Os
principais sistemas em que o OpenMp roda
são: Windows, Linux (Suse, RedHat,
Ubuntu ...), Mac e IBM.
9. Compiladores
Os principais compiladores com suporte para
OpenMP existentes no mercado são:
GNU - Compilador padrão dos sistemas linux
(gcc para C, g++ para C++ e gfortran para
Fortran)
IBM - Compilador para os sistemas linux e AIX
(C, C++, Fortran)
Oracle - Compilador para os sistemas linux
Solaris (C, C++, Fortran)
Intel - Compilador para os sistemas linux,
windows e MacOSX (C, C++, Fortran)
10. Modelo de Funcionamento
O modelo de funcionamento do OpenMp é
baseado no Fork-Join Model. Esse modelo
consiste basicamente em selecionar um ponto,
ou mais, onde o código se divide e outro, ou
outros, onde ele de junta em um único
processo. É importante ressaltar que quase
sempre terá um processo, chamado de Master
Thread, responsável por dividir e juntar os
outros.
Um importante detalhe é a sincronização dos
processsos, a qual é feita quando ocorre a
junção dos mesmos em uma barreira implícita.
11.
A divisão pode ser feita tanto manualmento,
como no MPI, quanto "automaticamente" pelo
compilador.
Cada processo terá um numero de
identificação (ID) único, sendo que o de
número 0 sempre será o Master-Thread.
O numero de ID pode ser usado para
especificar funções para um único thread.
12. Estruturação de um programa
Basicamente temos um código desse tipo com
os seguintes elementos:
14. Formato das Diretivas em Fortran
Todas as diretivas do OpenMp devem começar
com:
!$OMP
C$OMP
*$OMP
Sendo a primeira a mais usada.
Exemplo:
!$OMP PARALLEL DEFAULT(SHARED) PRIVATE(BETA,PI)
No Fixed Form, os comando !$OMP deve começar na
1 coluna e as Diretivas na 6 coluna.
15.
As diretivas sempre possuem o formato:
!$OMP [directive] [clause …]
!$OMP END [directive]
16. Regras Gerais
Os comentários não devem aparecer na
mesma linha das diretivas.
Somente uma especificação de diretiva por
diretiva.
As diretivas devem sempre vir em pares, um
para o inicio e outro para o final, o end é
opcional mas recomendado para legibilidade:
17. Tipos de Deretivas
Região de Construção Paralela (PARALLEL)
É o bloco onde o código será executado em
multiplos cabeçalhos:
18.
Os principais parametros ”Clause” podem ser:
private (list):
as variáveis da lista ficam privadas a cada proc
esso do Grupo de processos. Não são
inicializadas automaticamente com um valor.
firstprivate(list):
permite que as variáveis privadas sejam iniciali
zadas.
shared (list):
as variáveis são compartilhadas por todos os
outros processos.
19.
O código abaixo é um exemplo do uso de Parallel,
ele apresenta na tela o ID do processo que está
executando o programa e faz com que o cabeçalho
de ID igual a 0 apresente o número de processos.
20.
Construtores Work-Sharing:
São construtores onde é definido como será
compartilhado.
Podem ser:
DO / for: compartilham os processos iterativos,
representam o ”data parallelim”.
SECTIONS: compartilha um processos dentro
de somente alguns threads, representa:
”functional parallelism”.
SINGLE: realiza um processo dentro de
somente um thread.
24.
DO/FOR: Especifica que o próximo loop deverá ser
dividido entre os times de thread. Assume que o
comando ”PARALLEL” foi chamado, caso contrário,
ele não será dividido.
Estrutura do comando:
25.
Clauses:
SCHEDULE: Informa como as iterações do loop
serão divididas entre os threads. É possivel deixar
a devinição padrão.
STATIC: O Loop é dividido em um numero de
pedaços definido pela variável chunk, caso não
especificada, as iterações são divididas, se
possivel, continuamente entre todos os
processos.
DYNAMIC: O loop é dividido entre os
processos só que de forma dinâmica, ou seja,
quando thread fica livre é automaticamente é
encaminhado a fazer outro processo. O valor
padrão de chunk é 1.
26.
GUIDED: Semelhante ao DYNAMIC, com a
diferença de que a iteração é dividida em
blocos de forma de forma que eles possam ser
subdivididos em outros sub-blocos. Portanto
seu tamanho é reduzido quando termina cada
iteração. O tamanho inicial dos blocos é
proporcional a:
number_of_iterations / number_of_threads:
Conseguentemente:
number_of_iterations_remaining /
number_of_threads: A variável chunk define o
numero mínimo de cada bloco, o padrão é 1.
27.
RUNTIME: O SCHEDULING é adiado até a
execução da variável OMP_SCHEDULE. Não
pode especificar a variável chunk.
AUTO: O scheduling é decidido pelo compilar e
pelo sistema.
NO WAIT / nowait: Se especificado, os threads não
sincronizarão até o fim do loop paralelo.
ORDERED: Diz ao compilador executar as
iterações do loop como se elas estivessem em um
programa não paralelizado.
28.
COLLAPSE: Especifica em quantos loops um loop
deve ser desmontado em um grande processo
iterativo, de acordo com a cláusula SCHEDULE. A
sequencia das iterações nos loops determina a
ordem do processo de desmontamento no espaço
iterativo.
29. Compilando usando o GCC
Para compilar o código omp_hello (anexo à
apresentação) em fortram usando o GCC
presisamos instalar o gfortran dando o seguinte
comando no terminal:
$ sudo apt-get install gfortran
Após isso, basta compilar o código usando os
comandos:
$ gfortran -o omp_hellof -fopenmp omp_hello.f
Antes de executar, precisamos definir o
número de threads:
$ export OMP_NUM_THREADS=4
30.
Agora basta executar:
$ ./omp_hellof
Resultado para o nosso código é:
Hello World from thread = 2
Hello World from thread = 1
Hello World from thread = 3
Hello World from thread = 0
Number of threads = 4
O simbolo $ foi usado para indicar que o
comando é dado no terminal, mas ele não é
para ser digitado.
31. Referências
https://computing.llnl.gov/tutorials/openMP/ -
OpenMP, Blaise Barney, Lawrence Livermore
National Laboratory - acesso em 15/04/2012.
http://www.dcc.fc.up.pt/~fds/aulas/PPD/0708/int
ro_openmp-1x2.pdf – Introdução ao OpenMP,
Fernando Silva, DCC - FCUP - acesso em
15/04/2012.
http://www.dartmouth.edu/~rc/classes/intro_ope
nmp/compile_run.html - How to Compile and
Run an OpenMP Program, - acesso em
15/04/2012.