Exemplo de uma implementação MPI em C: Comunicação em Anel
Atualizado em:
[caption id="attachment_886" align="alignright" width="260"] Comunicação em Anel usando MPI[/caption]
Exemplo de uma implementação em MPI (Message Passing Interface) na linguagem C, que envia um valor pelos processadores no formato de um anel, por exemplo: o primeiro processador envia para o segundo que envia para o terceiro, assim por diante até o último enviar para o primeiro.
Para instalar e rodar o OpenMPI no Linux, veja esta post que escrevi: Olá Mundo com MIP em C
Na execução do programa há a opção de definir o número de voltas, e é contabilizado o tempo em segundos de cada volta e o tempo total no final.
Código fonte
comunicacao-anel.c
#include#include #include int size, rank, msg, tag, voltas; int main(int argc, char *argv[]){ MPI_Status stat; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&size); MPI_Comm_rank(MPI_COMM_WORLD,&rank); //Passar o número de voltas no parâmentro, caso contrário o numero de voltas será 1 if (argc>1){ voltas = atoi(argv[1]); }else{ voltas = 1; } int controleVoltas = 1; int proximo = rank + 1; int anterior = rank - 1; double startTime, voltaAnterior; //Controla que é o proximo e o anterior if (rank==size-1){ proximo = 0; } if (rank==0){ anterior = size-1; } //Se for o 0 inicia o envio if(rank==0){ msg = 42; tag = 0; voltaAnterior = startTime = MPI_Wtime(); MPI_Send(&msg, 1, MPI_INT, proximo, tag, MPI_COMM_WORLD); printf("Processo %d enviou %d para %d.\n", rank, msg, proximo); } //Roda o valor enquanto o número de voltas não for ultrapassado while (controleVoltas<=voltas){ controleVoltas++; //Aguarda o recebimento do proc. anterior MPI_Recv(&msg, 1, MPI_INT, anterior, tag, MPI_COMM_WORLD, &stat); printf("Processo %d recebeu %d de %d.\n", rank, msg, anterior); //Se voltar para o 0 marca o tempo da volta if (rank==0){ double tempoVolta = MPI_Wtime(); printf("Tempo da volta %d: %f segundos\n",controleVoltas-1,tempoVolta-voltaAnterior); voltaAnterior = tempoVolta; } //Se voltar para o 0 e não tiver mais voltas, encerra o loop if (rank==0 && controleVoltas>voltas) continue; //Envia o valor para o próximo proc. MPI_Send(&msg, 1, MPI_INT, proximo, tag, MPI_COMM_WORLD); printf("Processo %d enviou %d para %d.\n", rank, msg, proximo); } //No fim o 0 marca o tempo total if (rank==0){ double tempo = MPI_Wtime(); printf("Tempo total: %f segundos\n",tempo-startTime); } MPI_Finalize(); }
Execução
Para executar: mpirun -np {num_proc} comunicacao-anel {num_voltas}
Saída da execução com 4 processadores e 1 volta:
$mpirun -np 4 comunicacao-anel 1 Processo 0 enviou 42 para 1. Processo 1 recebeu 42 de 0. Processo 1 enviou 42 para 2. Processo 2 recebeu 42 de 1. Processo 2 enviou 42 para 3. Processo 0 recebeu 42 de 3. Tempo da volta 1: 0.000147 segundos Tempo total: 0.000160 segundos Processo 3 recebeu 42 de 2. Processo 3 enviou 42 para 0.
Saída da execução com 4 processadores e 2 voltas:
$mpirun -np 4 comunicacao-anel 2 Processo 0 enviou 42 para 1. Processo 0 recebeu 42 de 3. Tempo da volta 1: 0.000206 segundos Processo 0 enviou 42 para 1. Processo 0 recebeu 42 de 3. Tempo da volta 2: 0.000026 segundos Tempo total: 0.000235 segundos Processo 1 recebeu 42 de 0. Processo 1 enviou 42 para 2. Processo 1 recebeu 42 de 0. Processo 1 enviou 42 para 2. Processo 2 recebeu 42 de 1. Processo 2 enviou 42 para 3. Processo 2 recebeu 42 de 1. Processo 2 enviou 42 para 3. Processo 3 recebeu 42 de 2. Processo 3 enviou 42 para 0. Processo 3 recebeu 42 de 2. Processo 3 enviou 42 para 0.
Conclusão
Este foi um exemplo simples de uso do MPI, que é uma ferraenta muit poderosa para processamento paralelo.
[]'s
Deixe um comentário