MPI Pi calculation

10
INSTITUTO TECNOLÓGICO DE AERONÁUTICA Avenida Marechal Eduardo Gomes, S/N' DCTA São José dos Campos SP CE-265 Processamento paralelo Exercício #5 Professor: Dr. Jairo Panetta Alunos: Rafael Salema Marques 02 de abril de 2015

description

MPI Pi calculation

Transcript of MPI Pi calculation

Page 1: MPI Pi calculation

INSTITUTO TECNOLÓGICO DE AERONÁUTICA

Avenida Marechal Eduardo Gomes, S/N' – DCTA – São José dos Campos – SP

CE-265 – Processamento paralelo

Exercício #5

Professor: Dr. Jairo Panetta

Alunos: Rafael Salema Marques

02 de abril de 2015

Page 2: MPI Pi calculation

2

SUMÁRIO

1   VERSÃO PARALELA SeqPi.c ......................................................................................... 3  

2   ARQUIVO DE SAÍDA (Pi_1M_2^30.out) ....................................................................... 7  

3   ARQUIVO DE SAÍDA (Pi_2M_2^30.out) ....................................................................... 7  

4   ARQUIVO DE SAÍDA (Pi_4M_2^30.out) ....................................................................... 7  

5   ARQUIVO DE SAÍDA (Pi_8M_2^30.out) ....................................................................... 8  

6   SpeedUp .............................................................................................................................. 8  

7   Análise de resultados .......................................................................................................... 9  

Page 3: MPI Pi calculation

3

1 VERSÃO PARALELA SeqPi.c

#include <math.h> #include <stdio.h> #include <stdlib.h> #include <mpi.h> float wall_time(void); // inCircle: generate "points" random points at domain // (xStart, yStart) : (xStart+xRange, yStart+yRange), // that is a part of the square (-1.,-1):(1,1) and // count how many of these points lye inside the // unit circle long inCircle(long points, // # random pairs to generate float xStart, // start point at x domain float xRange, // range of x domain float yStart, // start point at y domain float yRange) // range of y domain { long count; long inside; int randVal; float xRand; float yRand; // random point is (xStart,yStart) + random fraction // of (xRange,yRange); // inside unit circle iff distance to origin <= 1.0 inside=0; for (count=0; count<points; count++) { randVal=rand(); xRand = xStart + xRange*(float)randVal/(float)RAND_MAX; randVal=rand(); yRand = yStart + yRange*(float)randVal/(float)RAND_MAX; if (xRand*xRand + yRand*yRand <= 1.0) inside++; } return inside; } int main(int argc, char *argv[]) { int procs=1; int pow; float xStart, xRange; float yStart, yRange; long points; long inside;

Page 4: MPI Pi calculation

4

float tend, tstart; double computedPi, referencePi, relError; int root=0; int i; double pi_arr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; double somaPi; double mediaPi; /////////////////////////////////////////////////////////////////////////////// // input arguments /////////////////////////////////////////////////////////////////////////////// if (argc != 2) { printf(" use: <exec> <exponent> (range [0:30]) \n"); return -1; } pow = atoi(argv[1]); if (pow < 0 || pow > 30) { printf(" exponent (%d) outside range [0:30] \n", pow); return -1; } points = 1L << pow; /////////////////////////////////////////////////////////////////////////////// // Inicializando MPI /////////////////////////////////////////////////////////////////////////////// MPI_Init(NULL, NULL); int size; MPI_Comm_size(MPI_COMM_WORLD, &size); int id; MPI_Comm_rank(MPI_COMM_WORLD, &id); // Get the name of the processor char processor_name[MPI_MAX_PROCESSOR_NAME]; int name_len; MPI_Get_processor_name(processor_name, &name_len); //printf("Inicializado a partir do processador %s, com o id #%d de um total de

%d processadores\n", processor_name, id, size); float dominio; float tamLocal; float inicio; dominio = 2; tamLocal = dominio/size;

Page 5: MPI Pi calculation

5

///////////////////////////////////////////////////////////// // divisão do domínio X ///////////////////////////////////////////////////////////// inicio = -1; inicio = inicio + (tamLocal * id); printf("id# %d inicio=%f no eixo x e range=%f\n", id, inicio, tamLocal); ///////////////////////////////////////////////////////////// // square that circumscribes unit circle ///////////////////////////////////////////////////////////// xStart=inicio; xRange=tamLocal; yStart=-1.0; yRange=2.0; //divide a quantidade de pontos pela quantidade de processos points = points/size; ///////////////////////////////////////////////////////////// // compute pi and measure execution time ///////////////////////////////////////////////////////////// tstart = wall_time(); inside = inCircle(points, xStart, xRange, yStart, yRange); computedPi = 4.0* ((double)inside/(double)points); tend = wall_time() - tstart; ///////////////////////////////////////////////////////////////////////// MPI_Send(&computedPi, 1, MPI_DOUBLE, 0, id, MPI_COMM_WORLD); printf("id# %d enviou a mensagem de computedPi=(%f) para o id# %d \n", id,

computedPi, root); //aguarda todos enviarem a mensagem MPI_Barrier( MPI_COMM_WORLD ); if (id == root) { for (i=0; i < size; i++) { if (i == 0) { pi_arr[0] = computedPi; printf("id# %d calculou computedPi=(%f)\n", id, pi_arr[i]); somaPi = somaPi + pi_arr[0]; } else { MPI_Recv(&pi_arr[i], 1, MPI_DOUBLE, i, i, MPI_COMM_WORLD,

MPI_STATUS_IGNORE);

Page 6: MPI Pi calculation

6

printf("id# %d recebeu a mensagem de computedPi=(%f) do id# %d \n", id, pi_arr[i], i);

somaPi = somaPi + pi_arr[i]; } } printf("Pi medio=%9.7f\n", somaPi/size); mediaPi = somaPi / size; // relative error and final dump referencePi = 2.0*asin(1.0); printf("Pi referencia=%9.7f\n", referencePi); relError = 100.0*fabs(mediaPi-referencePi)/referencePi; printf("pi=%9.7f, rel error %8.4f%%, %d procs, 2^%d points, %f(s) exec

time\n\n", mediaPi, relError, size, pow, tend); } MPI_Finalize(); return 0; }

Page 7: MPI Pi calculation

7

2 ARQUIVO DE SAÍDA (Pi_1M_2^30.out)

id# 0 inicio=-1.000000 no eixo x e range=2.000000

id# 0 enviou a mensagem de computedPi=(3.141590) para o id# 0

id# 0 calculou computedPi=(3.141590)

Pi medio=3.1415903

Pi referencia=3.1415927

pi=3.1415903, rel error 0.0001%, 1 procs, 2^30 points, 88.913216(s) exec time

3 ARQUIVO DE SAÍDA (Pi_2M_2^30.out)

id# 0 inicio=-1.000000 no eixo x e range=1.000000

id# 1 inicio=0.000000 no eixo x e range=1.000000

id# 0 enviou a mensagem de computedPi=(3.141682) para o id# 0

id# 1 enviou a mensagem de computedPi=(3.141540) para o id# 0

id# 0 calculou computedPi=(3.141682)

id# 0 recebeu a mensagem de computedPi=(3.141540) do id# 1

Pi medio=3.1416115

Pi referencia=3.1415927

pi=3.1416115, rel error 0.0006%, 2 procs, 2^30 points, 44.663998(s) exec time

4 ARQUIVO DE SAÍDA (Pi_4M_2^30.out)

id# 0 inicio=-1.000000 no eixo x e range=0.500000

id# 2 inicio=0.000000 no eixo x e range=0.500000

id# 3 inicio=0.500000 no eixo x e range=0.500000

id# 1 inicio=-0.500000 no eixo x e range=0.500000

id# 2 enviou a mensagem de computedPi=(3.826524) para o id# 0

id# 1 enviou a mensagem de computedPi=(3.826386) para o id# 0

id# 0 enviou a mensagem de computedPi=(2.456891) para o id# 0

id# 3 enviou a mensagem de computedPi=(2.456804) para o id# 0

id# 0 calculou computedPi=(2.456891)

id# 0 recebeu a mensagem de computedPi=(3.826386) do id# 1

id# 0 recebeu a mensagem de computedPi=(3.826524) do id# 2

id# 0 recebeu a mensagem de computedPi=(2.456804) do id# 3

Pi medio=3.1416511

Pi referencia=3.1415927

pi=3.1416511, rel error 0.0019%, 4 procs, 2^30 points, 22.659994(s) exec time

Page 8: MPI Pi calculation

8

5 ARQUIVO DE SAÍDA (Pi_8M_2^30.out)

id# 4 inicio=0.000000 no eixo x e range=0.250000

id# 2 inicio=-0.500000 no eixo x e range=0.250000

id# 0 inicio=-1.000000 no eixo x e range=0.250000

id# 5 inicio=0.250000 no eixo x e range=0.250000

id# 7 inicio=0.750000 no eixo x e range=0.250000

id# 1 inicio=-0.750000 no eixo x e range=0.250000

id# 3 inicio=-0.250000 no eixo x e range=0.250000

id# 6 inicio=0.500000 no eixo x e range=0.250000

id# 4 enviou a mensagem de computedPi=(3.957918) para o id# 0

id# 3 enviou a mensagem de computedPi=(3.957937) para o id# 0

id# 2 enviou a mensagem de computedPi=(3.694909) para o id# 0

id# 5 enviou a mensagem de computedPi=(3.695029) para o id# 0

id# 6 enviou a mensagem de computedPi=(3.100309) para o id# 0

id# 1 enviou a mensagem de computedPi=(3.100370) para o id# 0

id# 0 enviou a mensagem de computedPi=(1.813289) para o id# 0

id# 7 enviou a mensagem de computedPi=(1.813330) para o id# 0

id# 0 calculou computedPi=(1.813289)

id# 0 recebeu a mensagem de computedPi=(3.100370) do id# 1

id# 0 recebeu a mensagem de computedPi=(3.694909) do id# 2

id# 0 recebeu a mensagem de computedPi=(3.957937) do id# 3

id# 0 recebeu a mensagem de computedPi=(3.957918) do id# 4

id# 0 recebeu a mensagem de computedPi=(3.695029) do id# 5

id# 0 recebeu a mensagem de computedPi=(3.100309) do id# 6

id# 0 recebeu a mensagem de computedPi=(1.813330) do id# 7

Pi medio=3.1416365

Pi referencia=3.1415927

pi=3.1416365, rel error 0.0014%, 8 procs, 2^30 points, 11.868585(s) exec time

6 SpeedUp

  2^30  Proc  (qtd)   1   2   4   8  Tempo  (s)   88.957489   45.489933   23.896288   11.999891  speedup   1   1,955542   3,722648   7,413191  

Observando a tabela acima, obtivemos uma melhora considerável de performance com a

Page 9: MPI Pi calculation

9

divisão do domínio aplicada ao eixo X, resultados muito próximos aos casos ideais de

speedup, que seriam respectivamente 1, 2, 4 e 8.

7 Relação Erro x Quantidade de Processos

O programa faz uso de uma relação da entre o espalhamento

aleatório de pontos em uma área de um círculo de raio = 1 inscrito em

um quadrado para calcular Pi.

Essa relação leva em consideração a quantidade de pontos que

estão dentro ou fora da área do círculo.

A partir do momento em que se particiona o domínio (no presente caso o eixo X), cada

processo de nosso programa passa a tratar subdomínios diferentes no que diz respeito a

relação da área do círculo inscrito no quadrado, e consequentemente diferentes probabilidades

do ponto aleatório estar dentro ou fora da área do círculo.

Outro fato interessante que foi observado é que o erro tende a aumentar com a

quantidade de processos em paralelo. Salvo melhor juízo, entendo que quanto mais se divide

o domínio, mais heterogêneas serão as áreas para cálculo de Pi de cada processo, o que gera

valores diferentes no cálculo.

Por exemplo:

Para m=2 e n=30 o domínio X será dividido em 2 partes iguais da seguinte forma: Processo 0 1

Domínio -1.00 a 0.00 0.00 a 1.00

Cálculo de Pi 3.141682 3.141540

• Pi referência: 3.1415927 / Pi médio encontrado: 3.1416115

• Erro: 0.0006%

Para m=8 e n=30 o domínio X será dividido em 8 partes iguais da seguinte forma:

Processo 0 1 2 3 4 5 6 7

Domínio -1.00 a

-0.75

-0.75 a

-0.50

-0.50 a

-0.25

-0.25 a

0.00

0.00 a

0.25

0.25 a

0.50

0.50 a

0.75

0.75 a

1.00

Cálculo de Pi 1.813289 3.100370 3.694909 3.957937 3.957918 3.695029 3.100309 1.813330

• Pi referência: 3.1415927 / Pi médio encontrado: 3.1416365

• Erro: 0.0014%

Page 10: MPI Pi calculation

10

Como podemos perceber relacionando as informações das tabelas acima e o gráfico a

baixo, o cálculo de Pi dos processos (0 e 7), (1 e 6), (2 e 5) e (3 e 4) são similares entre si,

bem como seus domínios. Fato que corrobora a hipótese da área do circulo dentro do domínio

interferir diretamente no resultado de Pi. Ou seja, Pi é proporcional a área do círculo no

domínio.

Por fim, conclui-se que quanto maior a diferença dos valores de Pi nos subdomínios

maior será o erro. Consequentemente, quanto maior for a quantidade de processos, maior será

a diferença entre o menor Pi computado e o maior, aumentando assim o erro.

Acredito ainda que o arredondamento dos cálculos também contribui de forma modesta

com o erro no resultado final.

0,000000  

1,000000  

2,000000  

3,000000  

4,000000  

5,000000  

0   1   2   3   4   5   6   7  

pi  

pi