• Nenhum resultado encontrado

Aula 5 Computação Distribuída de Alto Desempenho

N/A
N/A
Protected

Academic year: 2021

Share "Aula 5 Computação Distribuída de Alto Desempenho"

Copied!
38
0
0

Texto

(1)

Aula 5

Computação Distribuída de Alto Desempenho

Marcelo Giovanni Marcelo Giovanni Nilton Alves

Nilton Alves

Marcelo Portes de Albuquerque Marcelo Portes de Albuquerque

Centro Brasileiro de Pesquisas Físicas

VI Escola do CBPF – Rio de Janeiro

17 a 28 de julho de 2006

(2)

Sumário Aula 05

1. 1. Programa C++ (Orienta Programa C++ (Orienta ç ç ão Objeto) ão Objeto)

2. 2. Laborat Laborat ó ó rios MPI rios MPI

BBáásico e Avansico e Avanççadoado

3. 3. Charm Charm ++ ++

(3)

3

Exemplo em C++

// classe contador class contador{

private:

unsigned int valor;

public:

contador( ){ // ---Æ Construtor valor = 0;

}

void inicializa(unsigned int val){

valor = val;

}

void incremento( ){

if (valor < 65535) valor++;

}

void decremento( ) {

if (valor > 0) valor--;

}

unsigned int get_valor( ){

return valor;

} };

// classe contador class contador{

private:

unsigned int valor;

public:

contador( ){ // ---Æ Construtor valor = 0;

}

void inicializa(unsigned int val){

valor = val;

}

void incremento( ){

if (valor < 65535) valor++;

}

void decremento( ) {

if (valor > 0) valor--;

}

unsigned int get_valor( ){

return valor;

} };

// Programa principal void main(){

contador cont;

unsigned int x;

cout << “\nValor inicial:"; cin >> x;

cont.inicializa(x);

cont.incremento();

cont.incremento();

cout << “\nValor final:“ <<

cont.get_valor();

}

// Programa principal void main(){

contador cont;

unsigned int x;

cout << “\nValor inicial:"; cin >> x;

cont.inicializa(x);

cont.incremento();

cont.incremento();

cout << “\nValor final:“ <<

cont.get_valor();

}

VI Escola do CBPF – Rio de Janeiro

OK!

(4)

Como Utilizar o MPI?

Bibliotecas

Adicione em seus programas o seguintes include para programas em C #include “mpi.h”

Rotinas MPI

Escreva seu programa fazendo chamadas às rotinas MPI

Para a compilação e linkedição utilizar os comandos:

mpicc [fonte.c] -o [executável] [parâmetros]

– Obs: O comando mpicc aceita os argumentos de compilação do compilador C

Execução

mpirun -[argumentos] [executável]

Exemplo: mpirun -np 5 a.out (executa a.out em 5 processadores)

Nomenclatura das Rotinas MPI

rc = MPI_Xxxxx(parâmetros, ...);

– rc é uma variável inteira que recebe um código de erro

(5)

5

MPI_Init

#include <stdio.h>

#include "mpi.h“

main(int argc, char *argv[]){

int ret;

ret = MPI_Init(&argc, &argv);

if (ret < 0){

printf ("Nao foi possivel inicializar o processo MPI!\n");

return;

} else ...

}

#include <stdio.h>

#include "mpi.h“

main(int argc, char *argv[]){

int ret;

ret = MPI_Init(&argc, &argv);

if (ret < 0){

printf ("Nao foi possivel inicializar o processo MPI!\n");

return;

} else ...

}

Inicia um processo MPI

Inicializa o processo MPI no processador

Deve ser a primeira rotina a ser chamada por cada processo Estabelece o ambiente necessário para executar o MPI Sincroniza a inicialização de todos os processos

Sintaxe (em C):

int MPI_Init (int *argc, char *argv[]) Parâmetros:

– argc – Quantidade de parâmetros da linha de comando – argv – ponteiro para os parâmetros da linha de comando

(6)

MPI_Comm_rank

Identifica um processo MPI dentro de um determinado grupo

Retorna sempre um valor inteiro entre 0 e n-1, onde n é o número de processos

Sintaxe (em C) : int MPI_Comm_rank (MPI_Comm comm, int *rank) Parâmetros:

comm - Comunicador do MPI

rank - Variável inteira com o número de identificação do processo

#include <stdio.h>

#include "mpi.h"

main(int argc, char *argv[]){

int mpierr, rank;

mpierr = MPI_Init(&argc, &argv);

if (mpierr < 0){

printf ("Nao foi possivel inicializar o processo MPI!\n");

return;

} else{

#include <stdio.h>

#include "mpi.h"

main(int argc, char *argv[]){

int mpierr, rank;

mpierr = MPI_Init(&argc, &argv);

if (mpierr < 0){

printf ("Nao foi possivel inicializar o processo MPI!\n");

return;

} else{

(7)

7

MPI_Comm_Size

Retorna o número de processos dentro de um grupo

Sintaxe (em C): int MPI_Comm_size (MPI_Comm comm, int *size)

Parâmetros:

comm: Comunicador do MPI

size: Variável interna que retorna o número de processos iniciados pelo MPI

#include <stdio.h>

#include "mpi.h"

main(int argc, char *argv[]){

int mpierr, rank, size;

mpierr = MPI_Init(&argc, &argv);

if (mpierr < 0){

printf ("Nao foi possivel inicializar o processo MPI!\n");

return;

} else{

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

printf ("Minha identificação no MPI e':%d\n",rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

printf("O numero de processos e': %d\n",size);

...

} }

#include <stdio.h>

#include "mpi.h"

main(int argc, char *argv[]){

int mpierr, rank, size;

mpierr = MPI_Init(&argc, &argv);

if (mpierr < 0){

printf ("Nao foi possivel inicializar o processo MPI!\n");

return;

} else{

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

printf ("Minha identificação no MPI e':%d\n",rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

printf("O numero de processos e': %d\n",size);

...

} }

(8)

MPI_Send

Rotina para envio de mensagens no MPI

utiliza o modo de comunicação "blocking send" (envio bloqueante), o que traz maior segurança na transmissão da mensagem

Sintaxe (em C): int MPI_Send (void *sndbuf, int count, MPI_Datatype dtype, int dest, int tag, MPI_Comm comm)

Parâmetros:

Sndbuf - Identificação do buffer (endereço de onde os dados serão enviados) count - Número de elementos a serem enviados

dtype - Tipo de dado

dest - Identificação do processo destino tag - Rótulo (label) da mensagem

comm - MPI Communicator

(9)

9

MPI_Send

#include <stdio.h>

#include "mpi.h"

main(int argc, char *argv[]){

int mpierr, rank, size, tag=100, i;

char message[20];

mpierr = MPI_Init(&argc, &argv);

if (mpierr < 0){

printf ("Nao foi possivel inicializar o processo MPI!\n");

return;

}

else {

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

printf ("Minha identificação no MPI e':%d\n",rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

printf("O numero de processos e': %d\n",size);

if (rank == 0){

strcpy(message,"Ola', Mundo!\n");

for (i=1; i<size; i++)

MPI_Send(message, 13, MPI_CHAR, i, tag, MPI_COMM_WORLD);

} else

...

} }

#include <stdio.h>

#include "mpi.h"

main(int argc, char *argv[]){

int mpierr, rank, size, tag=100, i;

char message[20];

mpierr = MPI_Init(&argc, &argv);

if (mpierr < 0){

printf ("Nao foi possivel inicializar o processo MPI!\n");

return;

}

else {

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

printf ("Minha identificação no MPI e':%d\n",rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

printf("O numero de processos e': %d\n",size);

if (rank == 0){

strcpy(message,"Ola', Mundo!\n");

for (i=1; i<size; i++)

MPI_Send(message, 13, MPI_CHAR, i, tag, MPI_COMM_WORLD);

} else

...

} }

int MPI_Send (void *sndbuf, int count, MPI_Datatype dtype, int dest, int tag, MPI_Comm comm) // 1234567890123

(10)

MPI_Recv

Rotina para recepção de mensagens no MPI

– utiliza o modo de comunicação "blocking receive" (recepção bloqueante), de forma que o processo espera até que a mensagem tenha sido recebida

Sintaxe (em C):

int MPI_Recv (void *sendbuf, int count, MPI_Datatype dtype,

int source, int tag, MPI_Comm comm, MPI_Status status)

Parâmetros:

sndbuf - Identificação do buffer de onde os dados serão armazenados count - Número de elementos a serem recebidos

dtype - Tipo de dado

source - Identificação do processo emissor tag - Rótulo (label) da mensagem

comm - MPI Communicator

status - Vetor de informações envolvendo os parâmetros source e tag

(11)

11

MPI_Recv

#include <stdio.h>

#include "mpi.h“

main(int argc, char *argv[]){

int mpierr, rank, size, tag=100, i;

MPI_Status status;

char message[20];

mpierr = MPI_Init(&argc, &argv);

if (mpierr < 0){

printf ("Nao foi possivel inicializar o processo MPI!\n");

return;

} else{

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

printf ("Minha identificação no MPI e':%d\n",rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

printf("O numero de processos e': %d\n",size);

if (rank == 0){

strcpy(message,"Ola', Mundo!\n");

for (i=1; i < size; i++)

MPI_Send(message, 13, MPI_CHAR, i, tag, MPI_COMM_WORLD);

} else{

MPI_Recv(message, 20, MPI_CHAR, 0, tag, MPI_COMM_WORLD, &status);

printf("Mensagem do no' %d : %s\n", rank, message);

...

} }

#include <stdio.h>

#include "mpi.h“

main(int argc, char *argv[]){

int mpierr, rank, size, tag=100, i;

MPI_Status status;

char message[20];

mpierr = MPI_Init(&argc, &argv);

if (mpierr < 0){

printf ("Nao foi possivel inicializar o processo MPI!\n");

return;

} else{

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

printf ("Minha identificação no MPI e':%d\n",rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

printf("O numero de processos e': %d\n",size);

if (rank == 0){

strcpy(message,"Ola', Mundo!\n");

for (i=1; i < size; i++)

MPI_Send(message, 13, MPI_CHAR, i, tag, MPI_COMM_WORLD);

} else{

MPI_Recv(message, 20, MPI_CHAR, 0, tag, MPI_COMM_WORLD, &status);

printf("Mensagem do no' %d : %s\n", rank, message);

...

} }

int MPI_Recv (void *sendbuf, int count, MPI_Datatype dtype,

int source, int tag, MPI_Comm comm, MPI_Status status)

(12)

MPI_Finalize

Finaliza um processo MPI

– Última rotina a ser chamada por cada processo.

– Sincroniza todos os processos na finalização de uma aplicação MPI

Sintaxe (em C)

int MPI_Finalize (void)

Parâmetros:

(Nenhum)

(13)

13

MPI_Finalize

#include <stdio.h>

#include "mpi.h“

main(int argc, char *argv[]){

int mpierr, rank, size, tag=100, i;

MPI_Status status;

char message[20];

mpierr = MPI_Init(&argc, &argv);

if (mpierr < 0){

printf ("Nao foi possivel inicializar o processo MPI!\n");

return;

} else{

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

printf ("Minha identificação no MPI e':%d\n",rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

printf("O numero de processos e': %d\n",size);

if (rank == 0){

strcpy(message,"Ola', Mundo!\n");

for (i=1; i < size; i++)

MPI_Send(message, 13, MPI_CHAR, i, tag, MPI_COMM_WORLD);

} else

MPI_Recv(message, 20, MPI_CHAR, 0, tag, MPI_COMM_WORLD, &status);

printf("Mensagem do no' %d : %s\n", rank, message);

MPI_Finalize();

} }

#include <stdio.h>

#include "mpi.h“

main(int argc, char *argv[]){

int mpierr, rank, size, tag=100, i;

MPI_Status status;

char message[20];

mpierr = MPI_Init(&argc, &argv);

if (mpierr < 0){

printf ("Nao foi possivel inicializar o processo MPI!\n");

return;

} else{

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

printf ("Minha identificação no MPI e':%d\n",rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

printf("O numero de processos e': %d\n",size);

if (rank == 0){

strcpy(message,"Ola', Mundo!\n");

for (i=1; i < size; i++)

MPI_Send(message, 13, MPI_CHAR, i, tag, MPI_COMM_WORLD);

} else

MPI_Recv(message, 20, MPI_CHAR, 0, tag, MPI_COMM_WORLD, &status);

printf("Mensagem do no' %d : %s\n", rank, message);

MPI_Finalize();

} }

OK!

(14)

MPI_Finalize

Job started at Mon Jul 17 16:56:31 BRST 2006 Minha identificação no MPI e':1

O numero de processos e': 4

Mensagem do no' 1 : Ola', Mundo!

Minha identificação no MPI e':3 O numero de processos e': 4

Mensagem do no' 3 : Ola', Mundo!

Minha identificação no MPI e':2 O numero de processos e': 4

Mensagem do no' 2 : Ola', Mundo!

Minha identificação no MPI e':0 O numero de processos e': 4

Mensagem do no' 0 : Ola', Mundo!

Job ended at Mon Jul 17 16:56:31 BRST 2006 Job started at Mon Jul 17 16:56:31 BRST 2006 Minha identificação no MPI e':1

O numero de processos e': 4

Mensagem do no' 1 : Ola', Mundo!

Minha identificação no MPI e':3 O numero de processos e': 4

Mensagem do no' 3 : Ola', Mundo!

Minha identificação no MPI e':2 O numero de processos e': 4

Mensagem do no' 2 : Ola', Mundo!

Minha identificação no MPI e':0 O numero de processos e': 4

Mensagem do no' 0 : Ola', Mundo!

Job ended at Mon Jul 17 16:56:31 BRST 2006

Output OK!

(15)

15

MPI_Bcast

Enviando dados para todos os processos

Diferentemente da comunicação ponto-a-ponto, na comunicação coletiva é possível enviar/receber dados simultaneamente de/para vários processos.

Sintaxe (em C) int MPI_Bcast (void *buf, int count,

MPI_Datatype datatype, int root, MPI_Comm comm)

Parâmetros:

buffer - Endereço do dado a ser enviado

count - Número de elementos a serem enviados datatype - Tipo do dado

root - Identifica o processo que irá efetuar o broadcast (origem) tag - Variável inteira com o rótulo da mensagem

comm - Identifica o Communicator

A0

processadores

Dados

Bcast

A0 A0

A0 A0

processadores

Dados

(16)

MPI_Bcast

#include <stdio.h>

#include "mpi.h"

main(int argc, char *argv[]){

int mpierr, rank, size, *index;

char message[20];

mpierr = MPI_Init(&argc, &argv);

if (mpierr < 0){

printf ("Nao foi possivel inicializar o processo MPI!\n");

return;

} else{

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

if (rank==0)

strcpy(message,"Mensagem do no 0\n");

MPI_Bcast(message, 20, MPI_CHAR, 0, MPI_COMM_WORLD);

printf("A mensagem recebida pelo rank (%d) foi: %s", rank, message);

MPI_Finalize();

#include <stdio.h>

#include "mpi.h"

main(int argc, char *argv[]){

int mpierr, rank, size, *index;

char message[20];

mpierr = MPI_Init(&argc, &argv);

if (mpierr < 0){

printf ("Nao foi possivel inicializar o processo MPI!\n");

return;

} else{

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

if (rank==0)

strcpy(message,"Mensagem do no 0\n");

MPI_Bcast(message, 20, MPI_CHAR, 0, MPI_COMM_WORLD);

printf("A mensagem recebida pelo rank (%d) foi: %s", rank, message);

MPI_Finalize();

OK!

Rank 0 define a mensagem a ser enviada Rank 0 define a mensagem a ser enviada

(17)

17

MPI_Bcast

Job started at Mon Jul 17 18:29:40 BRST 2006

A mensagem recebida pelo rank (1) foi: Mensagem do no 0 A mensagem recebida pelo rank (3) foi: Mensagem do no 0 A mensagem recebida pelo rank (0) foi: Mensagem do no 0 A mensagem recebida pelo rank (2) foi: Mensagem do no 0 Job ended at Mon Jul 17 18:29:40 BRST 2006

Job started at Mon Jul 17 18:29:40 BRST 2006

A mensagem recebida pelo rank (1) foi: Mensagem do no 0 A mensagem recebida pelo rank (3) foi: Mensagem do no 0 A mensagem recebida pelo rank (0) foi: Mensagem do no 0 A mensagem recebida pelo rank (2) foi: Mensagem do no 0 Job ended at Mon Jul 17 18:29:40 BRST 2006

Output OK!

r3 r2 r1 r0

message []

message []

message []

message []

“”

“”

“”

“Mensagem do no 0\n”

processadores

Broadcast

Dados

r3 r2 r1 r0

message []

message []

message []

message []

“Mensagem do no 0\n”

“Mensagem do no 0\n”

“Mensagem do no 0\n”

“Mensagem do no 0\n”

processadores

Dados

(18)

MPI_Scatter

Envia mensagens coletivamente

Envio de mensagens para um subgrupo de processos.

A mensagem pode ser segmentada e enviada para processos diferentes

Sintaxe (em C):

int MPI_Scatter (void *sbuf,int scount,MPI_Datatype stype, void *rbuf, int rcount,MPI_Datatype rtype,int root, MPI_Comm comm)

Parâmetros:

sbuf - Endereço dos dados a serem distribuídos

scount - Número de elementos enviados para cada processo stype - Tipo do dado a ser enviado

rbuf - Endereço onde os dados serão armazenados rcount - Quantidade de dados recebidos

rtype - Tipo do dado recebido

root - Identifica o processo que irá distribuir os dados comm - Identifica o Communicator

A3 A1 A2

A0

Dados

A0

Dados

(19)

19

MPI_Scatter

#include "mpi.h"

#include <stdio.h>

#define SIZE 4

int main(int argc, char *argv[]) {

int numtasks, rank, sendcount, recvcount, source;

float sendbuf[SIZE][SIZE] = {

{1.0, 2.0, 3.0, 4.0}, {5.0, 6.0, 7.0, 8.0}, {9.0, 10.0, 11.0, 12.0}, {13.0, 14.0, 15.0, 16.0}};

float recvbuf[SIZE];

MPI_Init(&argc,&argv);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

if (numtasks == SIZE){

source = 0;

sendcount = SIZE;

recvcount = SIZE;

MPI_Scatter(sendbuf, sendcount, MPI_FLOAT, recvbuf, recvcount, MPI_FLOAT, source, MPI_COMM_WORLD);

printf(" Results (%d): %3.0f %3.0f %3.0f %3.0f\n",rank, recvbuf[0], recvbuf[1], recvbuf[2], recvbuf[3]);

} else

printf("Must specify %d processors. Terminating.\n",SIZE);

MPI_Finalize();

}

#include "mpi.h"

#include <stdio.h>

#define SIZE 4

int main(int argc, char *argv[]) {

int numtasks, rank, sendcount, recvcount, source;

float sendbuf[SIZE][SIZE] = {

{1.0, 2.0, 3.0, 4.0}, {5.0, 6.0, 7.0, 8.0}, {9.0, 10.0, 11.0, 12.0}, {13.0, 14.0, 15.0, 16.0}};

float recvbuf[SIZE];

MPI_Init(&argc,&argv);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

if (numtasks == SIZE){

source = 0;

sendcount = SIZE;

recvcount = SIZE;

MPI_Scatter(sendbuf, sendcount, MPI_FLOAT, recvbuf, recvcount, MPI_FLOAT, source, MPI_COMM_WORLD);

printf(" Results (%d): %3.0f %3.0f %3.0f %3.0f\n",rank, recvbuf[0], recvbuf[1], recvbuf[2], recvbuf[3]);

} else

printf("Must specify %d processors. Terminating.\n",SIZE);

MPI_Finalize();

} int MPI_Scatter (void *sbuf,int scount,MPI_Datatype stype, void *rbuf, int rcount,MPI_Datatype rtype,int root, MPI_Comm comm)

OK!

buffer de envio buffer de envio

Rank 0 distribui para todos Rank 0 distribui para todos

buffer de recepção buffer de recepção

(20)

MPI_Scatter

Job started at Mon Jul 17 18:38:05 BRST 2006 Results (1): 5 6 7 8

Results (3): 13 14 15 16 Results (2): 9 10 11 12 Results (0): 1 2 3 4

Job ended at Mon Jul 17 18:38:05 BRST 2006 Job started at Mon Jul 17 18:38:05 BRST 2006 Results (1): 5 6 7 8

Results (3): 13 14 15 16 Results (2): 9 10 11 12 Results (0): 1 2 3 4

Job ended at Mon Jul 17 18:38:05 BRST 2006

Output OK!

sendbuf

r1

r0 9 10 11 12

16 15

14 13

8 7

6 5

4

2 3

1

Dados

adores

Dados

Scatter

recvbuf recvbuf

r1 r0

12 11

10 9

8 7

6 5

4 3

2 1

(21)

21

MPI_Gather

Coleta mensagens dos processos Sintaxe:

int MPI_Gather (void *sbuf, int scount, MPI_Datatype stype, void *rbuf, int rcount, MPI_Datatype rtype, int root, MPI_Comm comm)

Parâmetros:

sbuf - Endereço inicial do dado a ser coletado scount - Número de dados a serem coletados stype - Tipo do dado a ser coletado

rbuf - Endereço onde os dados serão armazenados rcount - Número de elementos recebidos por processo rtype - Tipo do dado recebido

root - Identifica o processo que irá efetuar a coleta comm - Identifica o Communicator

A2 A1

A3 A0

processadores

Dados

Gather

A3 A1 A2

A0

processadores

Dados

(22)

MPI_Gather

#include <stdio.h>

#include "mpi.h"

#define SIZE 4

int main(int argc, char *argv[]) {

int numtasks, rank, sendcount, recvcount, source, i;

float recvbuf[SIZE][SIZE];

float sendbuf[SIZE];

MPI_Init(&argc,&argv);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

if (numtasks == SIZE){

for (i=0;i<SIZE;i++)

sendbuf[i]=(float) rank * SIZE + i;

source = 0;

sendcount = SIZE; recvcount = SIZE;

MPI_Gather(sendbuf, sendcount, MPI_FLOAT, recvbuf, recvcount, MPI_FLOAT, source, MPI_COMM_WORLD);

if (rank==source)

for (i=0;i<SIZE;i++)

printf("Results (%d): %3.0f %3.0f %3.0f %3.0f\n", rank,

#include <stdio.h>

#include "mpi.h"

#define SIZE 4

int main(int argc, char *argv[]) {

int numtasks, rank, sendcount, recvcount, source, i;

float recvbuf[SIZE][SIZE];

float sendbuf[SIZE];

MPI_Init(&argc,&argv);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

if (numtasks == SIZE){

for (i=0;i<SIZE;i++)

sendbuf[i]=(float) rank * SIZE + i;

source = 0;

sendcount = SIZE; recvcount = SIZE;

MPI_Gather(sendbuf, sendcount, MPI_FLOAT, recvbuf, recvcount, MPI_FLOAT, source, MPI_COMM_WORLD);

if (rank==source)

for (i=0;i<SIZE;i++)

printf("Results (%d): %3.0f %3.0f %3.0f %3.0f\n", rank,

recvbuf[i][0], recvbuf[i][1], recvbuf[i][2], recvbuf[i][3]);

OK!

Rank 0 recebe de todos Rank 0 recebe de todos

Prepara buffer de envio Prepara buffer de envio

(23)

23

MPI_Gather

Job started at Mon Jul 17 19:24:01 BRST 2006 Results (0): 0 1 2 3

Results (0): 4 5 6 7 Results (0): 8 9 10 11 Results (0): 12 13 14 15

Job ended at Mon Jul 17 19:24:02 BRST 2006 Job started at Mon Jul 17 19:24:01 BRST 2006 Results (0): 0 1 2 3

Results (0): 4 5 6 7 Results (0): 8 9 10 11 Results (0): 12 13 14 15

Job ended at Mon Jul 17 19:24:02 BRST 2006

Output OK!

recvbuf

r3 r2 r1 r0

11 10

9 8

15 14

13 12

7 6

5 4

3

1 2

0

processadores

Dados

processadores

Dados Gather

sendbuf Sendbuf Sendbuf Sendbuf

15 14

13 12

r3

11 10

9 8

r2

7 6

5 4

r1

3 2

1 0

r0

(24)

MPI_Reduce

Realiza uma computação de todos os processos

– Todos os processos executam uma operação, onde o resultado parcial de cada processo é combinado e retornado para um processo específico

Sintaxe (em C)

int MPI_Reduce (void *sbuf, void *rbuf, int count,

MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm)

Parâmetros

sbuf - Endereço do dado a ser enviado;

rbuf - Endereço do dado a ser recebido;

count - Número de elementos a serem distribuídos;

datatype - Tipo do dado a ser computado;

op - Operaçâo a ser executada;

root - Processo que irá receber o resultado da operação;

comm - Identifica o Communicator;

(25)

25

MPI_Reduce

int, float Valor mínimo de menor índice

MPI_MINLOC

int, float Valor máximo de maior índice

MPI_MAXLOC

OU-EXCLUSIVO (XOR) lógico a nível de BIT int MPI_BXOR

OU-EXCLUSIVO (XOR) lógico int MPI_LXOR

OU (OR) lógico a nível de BIT int MPI_BOR

OU (OR) lógico int MPI_LOR

E (AND) lógico a nível de BIT int MPI_BAND

E (AND) lógico int MPI_LAND

int, float Produtório dos valores

MPI_PROD

int, float Somatório dos valores

MPI_SUM

int, float Valor mínimo

MPI_MIN

int, float Valor máximo

MPI_MAX

C Significado

Função

Operações Possíveis

(26)

MPI_Reduce

#include "mpi.h"

#include <stdio.h>

#define SIZE 4

int main(int argc, char *argv[]){

int numtasks, rank;

int recvbuf, sendbuf;

MPI_Init(&argc,&argv);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

sendbuf=rank;

if (numtasks == SIZE){

MPI_Reduce(&sendbuf, &recvbuf, 1, MPI_INT, MPI_MAX, 0, MPI_COMM_WORLD);

if (rank==0)

printf("Maior = %d\n", recvbuf);

} else

printf("Especifique %d processadores. Abortado.\n",SIZE);

#include "mpi.h"

#include <stdio.h>

#define SIZE 4

int main(int argc, char *argv[]){

int numtasks, rank;

int recvbuf, sendbuf;

MPI_Init(&argc,&argv);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

sendbuf=rank;

if (numtasks == SIZE){

MPI_Reduce(&sendbuf, &recvbuf, 1, MPI_INT, MPI_MAX, 0, MPI_COMM_WORLD);

if (rank==0)

printf("Maior = %d\n", recvbuf);

} else

printf("Especifique %d processadores. Abortado.\n",SIZE);

OK!

Rank 0 recebe o valor máximo Rank 0 recebe o valor máximo Em cada processo sendbuf

recebe o valor de rank Em cada processo sendbuf

recebe o valor de rank

(27)

27

MPI_Reduce

Job started at Mon Jul 17 19:21:59 BRST 2006 Maior = 3

Job ended at Mon Jul 17 19:21:59 BRST 2006 Job started at Mon Jul 17 19:21:59 BRST 2006 Maior = 3

Job ended at Mon Jul 17 19:21:59 BRST 2006

Output OK!

recvbuf recvbuf recvbuf recvbuf

sendbuf sendbuf sendbuf sendbuf

r3 r2 r1 r0

?

?

?

?

2 1

3 0

processadores

Reduce

Dados

3 2 1 0 MAX

recvbuf recvbuf recvbuf recvbuf

sendbuf sendbuf sendbuf sendbuf

r3 r2 r1 r0

?

?

? 3

2 1

3 0

processadores

Dados

(28)

Outras Rotinas Avançadas

MPI_Wtime

– Retorna (em precisão numérica dupla) o número de segundos decorridos desde algum tempo no passado

MPI_Wtick

– Retorna (em valor real) a precisão de tempo computada pelo comando MPI_Wtime

MPI_Get_processor_name

Retorna o nome da máquina onde um dado processo está executando

...

(29)

29

Organização dos Labs

Local: Prédio Min. João Alberto, 4º Andar, Laboratórios 1 e 3 Divisão da Turma em 2 Grupos

Grupo 1: 14h – 15h – “A até J”

Grupo 2: 15h – 16h – “L até Z”

Cluster dedicado à VI Escola: 6 CPUs

Login: esc1 Password: cbpf

Quinta (19/07)

Equação do segundo grau Compilação

Script pbs

Sexta (19/07)

MPI básico MPI avançado Integral em mpi charm++

Cluster do CBPF – andar térreo do prédio anexo

(30)

Integração Numérica

O conceito de integral está ligado ao problema da determinação da área de uma figura plana qualquer

Integral de uma função f(x) no intervalo [a,b]

f(x) F(x) =

ab f (x) dx Em determinados casos não podemos calcular F(x) ou a sua

obtenção não é simples

Em situações práticas nem sempre se tem a forma analítica da função f(x) a

ser integrada, mas sim uma tabela de pontos que descreve o comportamento da função

Em determinados casos não podemos calcular F(x) ou a sua

obtenção não é simples

Em situações práticas nem sempre se tem a forma analítica da função f(x) a

ser integrada, mas sim uma tabela de pontos que descreve o comportamento da função

(31)

31

Regra dos Trapézios

A idéia básica é a substituição da função f(x) por uma aproximação no intervalo [a,b]

Integrando no intervalo [x0 , x1] teremos

x1

f(x)

x0 x

O que é a fórmula da área do trapézio, como mostrado na figura

onde h = x1 x0

A = (B + b) * h / 2

[

( ) ( )

]

) 2

( 0 1

1

0

x f x

h f dx

x

x f

x +

B b

h

(32)

Regra dos Trapézios ...

Quanto maior for o intervalo, maior será o erro do método

O que se utiliza é subdividir o intervalo em vários pedaços, calcular a área de cada um deles e em seguida somar todos

[ ]

)) ( ) ( 2( ...

)) ( ) ( 2( )) ( ) ( 2( ) (

) ( ) 2 (

) (

1 2

1 1

0 1

0

1

n n

n

i

i i

x f x

h f x

f x

h f x

f x

h f x F

x f x h f

x F

+ +

+ +

+ +

+

= +

f(x)

n = 8

(33)

33

Implementação em MPI

x4 x x0 x1 x2 x3

f(x)

Passo p

rank 1

rank 1 rank 2rank 2 rank 3rank 3 rank 4rank 4

+ ResultadoFinal rank 0 rank 0

Cálculos parciais

result_parcial=0;

for ( i = (rank-1)*delta; i+p-precisao < (rank)*delta; i+=p ){

result_parcial += p * 0.5 * ( f(i)+ f(i+INC-precisao) );

}

result_parcial=0;

for ( i = (rank-1)*delta; i+p-precisao < (rank)*delta; i+=p ){

result_parcial += p * 0.5 * ( f(i)+ f(i+INC-precisao) );

}

P

#

0

4 x

x

=

... ...

x0 x0 + p precisão

Atenção

Σ r4 Σ r3 Σ r2 Σ r1

(34)

Cálculo da integral com f(x) = x no intervalo [ 0,10 ]

) 2

...

2 2 (

) (

)) 1 ( 9

, 0 ( 2 ...

) 1 , 0 ( 2 )

0 ( 2 (

) (

1 , 10 0

1 9

, 0 1

, 0

0 + + + +

+ +

+ +

=

=

e e

e h e

x F

f f

f h f

x F

a h b

Exemplo

1 50

0 =

=

x dx

Cálculo da integral com f(x) = ex no intervalo [ 0,1 ]

(35)

35

Hello

Hello

SayHi(int n) Hello

SayHi(int n)

# processadores = 6 2 Classes – Main e Hello

nElements = 10 objetos Hello (array objetos)

Main

Main done Main done

arr[0]

Hello

SayHi(n) SayHi(n)

Main

Main done Main done

arr[1]

Hello

SayHi(n) SayHi(n)

arr[9]

Hello

SayHi(n) SayHi(n)

...

arr[0].SayHi(17) arr[1].SayHi(17+1) arr[9].SayHi(17+9)

Main.done()

Hello Charm++ (Objects Array)

(36)

Charm++ Hello with Array Obj

#include <stdio.h>

#include "hello.decl.h"

CProxy_Main mainProxy; /*readonly*/

int nElements; /*readonly*/

class Main : public Chare{ /*mainchare*/

public:

--- Main(CkArgMsg* m) {

nElements=5; //Process command-line arguments if(m->argc >1 ) nElements=atoi(m->argv[1]);

delete m;

//Start the computation

CkPrintf("Running Hello on %d processors

for %d elements\n", CkNumPes(),nElements);

mainProxy = thishandle;

CProxy_Hello arr = CProxy_Hello::ckNew(nElements);

arr[0].SayHi(17);

};

#include <stdio.h>

#include "hello.decl.h"

CProxy_Main mainProxy; /*readonly*/

int nElements; /*readonly*/

class Main : public Chare{ /*mainchare*/

public:

--- Main(CkArgMsg* m) {

nElements=5; //Process command-line arguments if(m->argc >1 ) nElements=atoi(m->argv[1]);

delete m;

//Start the computation

CkPrintf("Running Hello on %d processors

for %d elements\n", CkNumPes(),nElements);

mainProxy = thishandle;

CProxy_Hello arr = CProxy_Hello::ckNew(nElements);

arr[0].SayHi(17);

};

/*array [1D]*/

class Hello : public CBase_Hello{

public:

--- Hello(){

CkPrintf("Hello %d created\n",thisIndex);

}

--- Hello(CkMigrateMessage *m) {}

--- void SayHi(int hiNo){

CkPrintf("Hi[%d] from element (%d)\n",hiNo,thisIndex);

if (thisIndex < nElements-1) //Pass the hello on:

thisProxy[thisIndex+1].SayHi(hiNo+1);

else

//We've been around once-- we're done.

mainProxy.done();

/*array [1D]*/

class Hello : public CBase_Hello{

public:

--- Hello(){

CkPrintf("Hello %d created\n",thisIndex);

}

--- Hello(CkMigrateMessage *m) {}

--- void SayHi(int hiNo){

CkPrintf("Hi[%d] from element (%d)\n",hiNo,thisIndex);

if (thisIndex < nElements-1) //Pass the hello on:

thisProxy[thisIndex+1].SayHi(hiNo+1);

else

//We've been around once-- we're done.

mainProxy.done();

(37)

37

Charm++ Hello with Array Obj

Compilando: > charmc -c hello.ci hello.C -o a.out -language charm++

Executando: > charmrun ++p3 a.out 10 Job started at Mon Aug 15 11:27:23 BRST 2005 Running Hello on 3 processors for 10 elements Hello 0 created

Hello 3 created Hello 6 created Hello 9 created

Hi[17] from element 0 Hello 2 created

Hello 5 created Hello 8 created Hello 1 created Hello 4 created Hello 7 created

Hi[18] from element 1 Hi[19] from element 2 Hi[20] from element 3 Hi[21] from element 4 Hi[22] from element 5 Hi[23] from element 6 Hi[24] from element 7 Hi[25] from element 8 Hi[26] from element 9 All done

Job ended at Mon Aug 15 11:27:25 BRST 2005

>

(38)

Aula 5

Computação Distribuída de Alto Desempenho

Marcelo Giovanni Marcelo Giovanni Nilton Alves

Nilton Alves

Marcelo Portes de Albuquerque Marcelo Portes de Albuquerque

Centro Brasileiro de Pesquisas Físicas

Referências

Documentos relacionados

Estaca de concreto moldada in loco, executada mediante a introdução no terreno, por rotação, de um trado helicoidal contínuo. A injeção de concreto é feita pela haste

A placa EXPRECIUM-II possui duas entradas de linhas telefônicas, uma entrada para uma bateria externa de 12 Volt DC e uma saída paralela para uma impressora escrava da placa, para

17.1 A Alfa Seguradora se reserva o direito de a qualquer tempo, durante a vigência deste contrato, proceder inspeção no local do Seguro, devendo o Segurado proporcionar todos

Controlador de alto nível (por ex.: PLC) Cabo da válvula Tubo de alimentação do ar de 4 mm Pr essão do fluido Regulador de pressão de precisão Regulador de pressão de

Para facilitar a compreens˜ao, a explica¸c˜ao do procedimento foi di- vidido em quatro etapas: (i) uma etapa inicial onde s˜ao explicadas as condi¸c˜oes iniciais da bancada para

221 a Tó”, apensa a uma informação do Oficial Público, datada de vinte e três de Março do corrente ano, deliberou, por unanimidade, ratificar o despacho do

Destaca Hennemann (2012, p.29), segundo os PCNs (1998) são necessários desenvolver nos cidadãos a capacidade de posicionar-se diante de questões que interferem

Desta forma, é de grande importância a realização de testes verificando a segurança de extratos vegetais de plantas como Manjerona (Origanum majorana) e Romã