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
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++
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
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
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
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{
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);
...
} }
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
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
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
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)
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)
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();
} }
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
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
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
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
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
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
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
Dadosr0
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
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
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
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 3Sendbuf
r1
4 5 6 7
Sendbuf
r2
8 9 10 11Sendbuf
r3
12 13 14 15sendbuf
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;
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
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
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
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
...
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: 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
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 ]
∫
=
ba
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)
∫
apodemos 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
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 11
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
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
0f x
1f x
1f x
2f x
n 1f x
nF ≈ + + + + +
−+
f(x)
n
n n
n = 8
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
0x
0+ p
precisão
Atenção
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
xxxxno 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
# 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)
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();
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