| | | | |

2.1 Olá, Mundo!

Ajude a manter o site livre, gratuito e sem propagandas. Colabore!

Em revisão

A computação paralela com MP inicia-se por uma instância de processamento master thread. Todas as instâncias de processamento disponíveis (threads) leem e escrevem variáveis compartilhadas. A ramificação (fork) do processo entre os threads disponíveis é feita por instrução explícita no início de uma região paralela do código. Ao final da região paralela, todos os threads sincronizam-se (join) e o processo segue apenas com o thread master. Veja a Figura 2.1.

Refer to caption
Figura 2.1: Fluxograma de um processo MP.

Vamos escrever nosso primeiro código MP. O Código 1 inicia uma região paralela e cada instância de processamento escreve “Olá” e identifica-se.

Código 1: ola.cc
1#include <stdio.h>
2
3// OpenMP API
4#include <omp.h>
5
6int main(int argc, char *argv[]) {
7
8  // região paralela
9  #pragma omp parallel
10  {
11    // id da instância de processamento
12    int id = omp_get_thread_num();
13
14    printf("Processo %d, olá!\n", id);
15  }
16
17  return 0;
18}

Na linha 4, o API OpenMP é incluído no código. A região paralela vale dentro do escopo iniciado pela instrução

# pragma omp parallel

i.e., entre as linhas 9 e 15. Em paralelo, cada thread registra seu número de identificação na variável interira id, veja a linha 12. Na linha 14, escrevem a saudação, identificando-se.

Para compilar este código, digite no terminal

1$ g++ -fopenmp ola.cc

Ao compilar, um executável a.out será criado. Para executá-lo, basta digitar no terminal:

1$ a.out

Ao executar, devemos ver a saída do terminal como algo parecido com

1Processo 0, olá!
2Processo 3, olá!
3Processo 1, olá!
4Processo 2, olá!

A saída irá depender do número de threads disponíveis na máquina e a ordem dos threads pode variar a cada execução. Execute o código várias vezes e analise as saídas!

Observação 2.1.1.

As variáveis declaradas dentro de uma região paralela são privadas de cada thread. As variáveis declaradas fora de uma região paralela são compartilhadas, sendo acessíveis por todos os threads.

2.1.1 Exercícios resolvidos

Em revisão

ER 2.1.1.

O número de instâncias de processamento pode ser alterado pela variável do sistema OMP_NUM_THREADS. Altere o número de threads para 2 e execute o Código 1.

Solução.

Para alterar o número de threads, pode-se digitar no terminal

$ export OMP_NUM_THREADS=2

Caso já tenha compilado o código, não é necessário recompilá-lo. Basta executá-lo com

$ ./a.out

A saída deve ser algo do tipo

Olá, processo 0
Olá, processo 1
ER 2.1.2.

Escreva um código MP para ser executado com 2 threads. O master thread deve ler dois números em ponto flutuante. Então, em paralelo, um dos threads deve calcular a soma dos dois números e o outro thread deve calcular o produto.

Solução.
Código 2: sp.cc
1#include <stdio.h>
2
3// OpenMP API
4#include <omp.h>
5
6using namespace std;
7
8int main(int argc, char *argv[]) {
9
10  double a,b;
11  printf("Digite o primeiro número: ");
12  scanf("%lf", &a);
13
14  printf("Digite o segundo número: ");
15  scanf("%lf", &b);
16
17  // regiao paralela
18  #pragma omp parallel
19  {
20    // id do processo
21    int id = omp_get_thread_num();
22
23    if (id == 0) {
24      printf("Soma: %f\n", (a+b));
25    }
26    else if (id == 1) {
27      printf("Produto: %f\n", (a*b));
28    }
29  }
30
31  return 0;
32}

2.1.2 Exercícios

Em revisão

E. 2.1.1.

Modifique o Código 1 de forma que cada thread escreva na tela “Processo ID de NP, olá!”, onde ID é a identificação do thread e NP é o número total de threads disponíveis. O número total de threads pode ser obtido com a função OpenMP

omp_get_num_threads()
E. 2.1.2.

Defina um número de threads maior do que o disponível em sua máquina. Então, rode o Código 1 e analise a saída. O que você observa?

E. 2.1.3.

Faça um código MP para ser executado com 2 threads. O master thread deve ler dois números a e b não nulos em ponto flutuante. Em paralelo, um dos thread deve computar ab e o outro deve computar a/b. Por fim, o master thread deve escrever (ab)+(a/b).

E. 2.1.4.

Escreva um código MP para computar a multiplicação de uma matriz n×n com um vetor de n elementos. Inicialize todos os elementos com números randômicos em ponto flutuante. Ainda, o código deve ser escrito para um número arbitrário m1 de instâncias de processamento. Por fim, compare o desempenho do código MP com uma versão serial do código.

E. 2.1.5.

Escreva um código MP para computar o produto de uma matriz n×m com uma matriz de m×n elementos, com nm. Inicialize todos os elementos com números randômicos em ponto flutuante. Ainda, o código deve ser escrito para um número arbitrário m>1 de instâncias de processamento. Por fim, compare o desempenho do código MP com uma versão serial do código.


Envie seu comentário

As informações preenchidas são enviadas por e-mail para o desenvolvedor do site e tratadas de forma privada. Consulte a Política de Uso de Dados para mais informações. Aproveito para agradecer a todas/os que de forma assídua ou esporádica contribuem enviando correções, sugestões e críticas!