• Nenhum resultado encontrado

VI Escola do CBPF - MESONPI

N/A
N/A
Protected

Academic year: 2023

Share "VI Escola do CBPF - MESONPI"

Copied!
38
0
0

Texto

(1)

Aula 5

Computação Distribuída de Alto Desempenho

CBPF

Centro Brasileiro de Pesquisas Físicas

de Alto Desempenho

Marcelo Portes de Albuquerque Marcelo Portes de Albuquerque Nilton Alves

Nilton Alves Marcelo Giovanni Marcelo Giovanni

VI Escola do CBPF – Rio de Janeiro

17 a 28 de julho de 2006

1

(2)

Sumário Aula 05

1.

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

2. Laboratórios MPI Laboratórios MPI

Básico e Avançado Básico e Avançado Básico e Avançado Básico e Avançado

3.

3. Charm++ Charm++

(3)

Exemplo em C++

// classe contador class contador{

private:

unsigned int valor;

public:

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

}

void inicializa(unsigned int val){

// Programa principal void main(){

contador cont;

unsigned int x;

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

cont.inicializa(x);

cont.incremento();

OK!

3 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;

} };

cont.incremento();

cont.incremento();

cout << “\nValor final:“ <<

cont.get_valor();

}

VI Escola do CBPF – Rio de Janeiro

(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]

– 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)

MPI_Init

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:

5

#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 ...

}

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 <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)

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"

7 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

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)

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);

9 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)

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{

11 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)

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{

OK!

13 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();

} }

(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!

Output OK!

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

(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

15

– 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");

OK!

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();

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

(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

Output OK!

Broadcast

17

r0

“Mensagem do no 0\n”

message []

r1 “”

message []

r2 “”

message []

r3 “”

message []

processadores

Broadcast

Dados

“Mensagem do no 0\n”

r0

message []

“Mensagem do no 0\n”

message []

r1

“Mensagem do no 0\n”

message []

r2

“Mensagem do no 0\n”

message []

r3

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

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

A0 A1 A2 A3

res

Dados

res

A0

Dados

(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);

OK!

buffer de envio buffer de envio

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

19 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)

Rank 0 distribui para todos

Rank 0 distribui para todos

(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

Output OK!

Dados

Scatter

Dados

r0

1 2 3 4

5 6 7 8

9 10 11 12

13 14 15 16

sendbuf

cessadores

r1

Dados

cessadores

Dados

Scatter

1 2 3 4

r0

recvbuf

5 6 7 8

r1

recvbuf

9 10 11 12

(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

21

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

A0 A1 A2 A3

processadores

Dados

Gather A0 A1 A2 A3

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){

OK!

Prepara buffer de envio Prepara buffer de envio

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]);

Rank 0 recebe de todos

Rank 0 recebe de todos

(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

Output OK!

Dados

Dados

Gather

23

0 1 2 3

r0

4 5 6 7

8 9 10 11

12 13 14 15

recvbuf

r1 r2 r3

processadores

processadores

r0

0 1 2 3

Sendbuf

r1

4 5 6 7

Sendbuf

r2

8 9 10 11

Sendbuf

r3

12 13 14 15

sendbuf

(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;

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)

MPI_Reduce

Função Significado C

MPI_MAX Valor máximo int, float

MPI_MIN Valor mínimo int, float

MPI_SUM Somatório dos valores int, float

MPI_PROD Produtório dos valores int, float

Operações Possíveis

25

MPI_PROD Produtório dos valores int, float

MPI_LAND E (AND) lógico int

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

MPI_LOR OU (OR) lógico int

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

MPI_LXOR OU-EXCLUSIVO (XOR) lógico int

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

MPI_MAXLOC Valor máximo de maior índice int, float

MPI_MINLOC Valor mínimo de menor índice int, float

(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);

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

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);

valor máximo

valor máximo

(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

Output OK!

Reduce

Dados Dados

27

r0 0 ?

sendbuf recvbuf

r1 1 ?

sendbuf recvbuf

r2 2 ?

sendbuf recvbuf

r3 3 ?

sendbuf recvbuf

processadores

Dados

MAX 0 1 2 3

r0 0 3

sendbuf recvbuf

r1 1 ?

sendbuf recvbuf

r2 2 ?

sendbuf recvbuf

r3 3 ?

sendbuf recvbuf

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_Wtime

MPI_Get_processor_name

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

...

(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

29

Login: esc1Password: cbpf

Quinta (19/07)

Equação do segundo grauCompilação

Script pbs

Sexta (19/07)

MPI básicoMPI avançadoIntegral em mpicharm++

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 ]

=

b

a

f x dx

x

F ( ) ( ) Em determinados casos não

podemos calcular F(x) F(x) F(x) F(x) ou a sua

f(x)

a

podemos calcular F(x) F(x) F(x) 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)

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 [ x

0

, x

1

] teremos

onde h = x

1

x

0

[ ( ) ( ) ]

) 2

(

0 1

1

0

x f x

h f dx

x

x

f

x

≅ +

x 1 31

f(x)

x 0 xxxx

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

A = (B + b) * h / 2 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

+ +

+ +

+ +

+

=

+

)) ( )

( 2 ( ...

)) ( )

( 2 ( )) ( )

( 2 ( )

( x f x

0

f x

1

f x

1

f x

2

f x

n 1

f x

n

F ≈ + + + + +

+

f(x)

n

n n

n = 8

(33)

Implementação em MPI

f(x)

Passo p

+ Resultado Final

rank 0

Cálculos parciais

Atenção

Σ r1 Σ r2 Σ r3 Σ r4

33

x 4 xxxx

x 0 x 1 x 2 x 3

rank 1 rank 2 rank 3 rank 4

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

=

... ...

x

0

x

0

+ p

precisão

Atenção

(34)

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

a b

Exemplo

1 50

0 =

= ∫ x dx

Cálculo da integral com f(x) = e f(x) = e f(x) = e f(x) = e

xxxx

no intervalo [ 0,1 ]

) 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

(35)

# processadores = 6

2 Classes – Main e Hello

nElements = 10 objetos Hello (array objetos)

Main

Main done

Main

Main done

Main.done()

Hello Charm++ (Objects Array)

35

Hello

Hello

SayHi(int n) done

arr[0]

Hello

SayHi(n)

arr[1]

Hello

SayHi(n)

arr[9]

Hello

SayHi(n)

...

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

(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;

/*array [1D]*/

class Hello : public CBase_Hello{

public:

--- Hello(){

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

}

--- Hello(CkMigrateMessage *m) {}

--- void SayHi(int hiNo){

//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);

};

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)

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

37

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

CBPF

Centro Brasileiro de Pesquisas Físicas

de Alto Desempenho

Marcelo Portes de Albuquerque Marcelo Portes de Albuquerque Nilton Alves

Nilton Alves Marcelo Giovanni Marcelo Giovanni

Referências

Documentos relacionados

Cria uma célula para guardar um elemento x e insere esta célula no início da lista ini!. void insere (int x, Celula