Vous êtes sur la page 1sur 7

Dentro de la computacin existe un conjunto de algoritmos destinados a la

determinacin de valores ptimos de constantes utilizadas en las ciencias exactas,


ejemplo de ello es el mtodo de Monte Carlo que se describe a continuacin:

1. El mtodo de Monte Carlo aplicado al clculo de PI


El mtodo
2

Dado que el rea del crculo es y el rea del cuadrado


que lo circunscribe es 4, la relacin entre ambas reas es
/4.
Esta relacin de reas es la misma en el cuadrante
superior derecho, donde se puede uno imaginar unos
ejes cartesianos con origen en el centro del crculo y
amplitud 1 en cada eje.

El mtodo consiste en elegir al azar puntos del


cuadrante (con coordenadas x, y comprendidas entre 0 y
1), de tal forma que se pueden contabilizar los puntos
que caen dentro del semicrculo.
Si el mtodo de elegir nmeros al azar es bueno y se prueba un determinado nmero
suficiente de veces, sea M, la relacin entre puntos que caen dentro del semicrculo y
puntos totales escogidos, debe ser una aproximacin a /4.
El esbozo de programa secuencial que calculara PI de esta forma es el siguiente:
enCirculo = 0;
for (i=1; i<=M; i++) {
x = aleatorio(0.0, 1.0);
y = aleatorio(0.0, 1.0);
if ((x*x + y*y)<=1.0) enCirculo++;
}
PI = (4.0 * enCirculo) / (double) M;

Versiones secuenciales
En este apartado se va a probar la ejecucin del algoritmo bsico contado en el apartado
anterior, pero con tres variantes que tienen que ver con la condicin de terminacin del
clculo:
En la primer versin del programa el cmputo termina tras un bucle que se ejecuta un
cierto nmero de veces, cuyo valor se fija con un parmetro en la lnea de comandos al
invocar el ejecutable. El cdigo es el siguiente:

// piUno.c: Programa que calcula el numero PI mediante el mtodo


//
de Monte Carlo basado en circulo de radio 1 inscrito en
//
Cuadrado de lado 2.
//
Terminacin controlada por: Numero de iteraciones
#include
#include
#include
#include
#include

<assert.h>
<math.h>
<stdlib.h>
<stdio.h>
<sys/time.h>

//-------------------------------------------------------------------int main( int


argc, char *argv[] ) {
int i, iteraciones, enCirculo=0;
double x, y, pi;
struct timeval t0, t1, t;
// Control parametro => Numero de iteraciones
if (argc != 2) {
printf ("Uso: piUno numIteraciones \n");
exit(0);
}
iteraciones = atoi(argv[1]);
assert (gettimeofday (&t0, NULL) == 0);
for (i=1; i<=iteraciones; i++) {
x = (double) random() / (double) RAND_MAX;
y = (double) random() / (double) RAND_MAX;
if ((x*x + y*y) <= 1.0) enCirculo++;
}
assert (gettimeofday (&t1, NULL) == 0);
timersub(&t1, &t0, &t);
pi = (4.0 * enCirculo) / (double) i;
printf ("Valor de PI = %.6lf\n", pi);
printf ("Error
= %.6lf\n", fabs(pi-M_PI));
printf ("Tiempo
= %ld:%ld(seg:mseg)\n", t.tv_sec,
t.tv_usec/1000);
return 0;
}

Generar el ejecutable de piUno.c


Ejecutar varias veces este comando con distintos valores de iteraciones y
rellenar la Tabla-1 de tiempos.
Reflexionar sobre las ganancias o prdidas de precisin del clculo de PI segn
hemos ido aumentando el nmero de iteraciones.
Ahora vamos a suponer que se conoce el valor real del nmero PI (constante M_PI
definida en la biblioteca matemtica math.h). Se puede cambiar el modelo del
programa para que haga iteraciones hasta que compute un valor de PI con un error
respecto del PI real, menor que un parmetro determinado.
Precisamente esto es lo que hace el programa piDos.c cuyo cdigo es el siguiente:

// piDos.c: Programa que calcula el numero PI mediante el mtodo


//
de Monte Carlo basado en circulo de radio 1 inscrito en
//
cuadrado de lado 2.
//
Terminacin controlada por: Error respecto de M_PI
#include
#include
#include
#include
#include

<assert.h>
<math.h>
<stdlib.h>
<stdio.h>
<sys/time.h>

#define MAX_ITER 1000000000


int main( int

argc, char *argv[] ) {

int i, enCirculo=0;
double x, y, pi, cotaError;
struct timeval t0, t1, t;
// Control parametro => Cota del error
if (argc != 2) {
printf ("Uso: piDos cotaError \n");
exit(0);
}
cotaError = atof(argv[1]);
assert (gettimeofday (&t0, NULL) == 0);
for (i=1; i<=MAX_ITER; i++) {
x = (double) random() / (double) RAND_MAX;
y = (double) random() / (double) RAND_MAX;
if ((x*x + y*y) <= 1.0) enCirculo++;
pi = (4.0 * enCirculo) / (double) i;
if (fabs(pi - M_PI) < cotaError) break;
}
assert (gettimeofday (&t1, NULL) == 0);
timersub(&t1, &t0, &t);
printf ("Valor de PI = %.10lf en iteracion = %d\n", pi, i);
printf ("Tiempo
= %ld:%ld(seg:mseg)\n", t.tv_sec,
t.tv_usec/1000);
return 0;
}

Generar el ejecutable de piDos.c


Ejecutar varias veces este comando con distintos valores de cota del error y
rellenar la Tabla-2 de tiempos.
Comparar los resultados obtenidos en esta prueba (piDos) respecto de la anterior
(piUno).
Finalmente, se adopta otro modelo de terminacin que persigue acotar el error, pero sin
conocer el valor real de PI. Una forma de hacerlo es iterar hasta que se consigan dos
valores consecutivos de PI que se diferencien en menos de una cota de error fijada como
parmetro. Esto es lo que hace el programa piTres.c cuyo cdigo es el siguiente:

// piTres.c: Programa que calcula el numero PI mediante el mtodo


//
de Monte Carlo basado en circulo de radio 1 inscrito en
//
cuadrado de lado 2.
//
Terminacin controlada por: Error respecto piAnterior
#include
#include
#include
#include
#include

<assert.h>
<math.h>
<stdlib.h>
<stdio.h>
<sys/time.h>

#define MAX_ITER 1000000000


//-------------------------------------------------------------------int main( int
argc, char *argv[] ) {
int i, enCirculo=0;
double x, y, piActual, piAnterior=3.0, cotaError, elError;
struct timeval t0, t1, t;
// Control parametro => Error respecto piAnterior
if (argc != 2) {
printf ("Uso: piTres cotaError \n");
exit(0);
}
cotaError = atof(argv[1]);
assert (gettimeofday (&t0, NULL) == 0);
for (i=1; i<=MAX_ITER; i++) {
x = (double) random() / (double) RAND_MAX;
y = (double) random() / (double) RAND_MAX;
if ((x*x + y*y) <= 1.0) enCirculo++;
piActual = (4.0 * enCirculo) / (double) i;
elError = fabs(piActual - piAnterior);
if ((elError > 0.0) && (elError < cotaError)) break;
piAnterior = piActual;
}
assert (gettimeofday (&t1, NULL) == 0);
timersub(&t1, &t0, &t);
printf ("Valor de PI = %.6lf en iteracion = %d\n", piActual, i);
printf ("Error
= %.6lf\n", fabs(piActual - M_PI));
printf ("Tiempo
= %ld:%ld(seg:mseg)\n", t.tv_sec,
t.tv_usec/1000);
return 0;
}

Generar el ejecutable de piTres.c.


Ejecutar varias veces este comando con distintos valores para la cota del error y
rellenar la Tabla-3 de tiempos.
Comparar los resultados obtenidos en esta prueba (piTres) respecto de las
anteriores (piUno y piDos).

Tablas de tiempos
Tabla-1. Tiempos de la versin piUno (#iteraciones)
# Iteraciones

PI

Error

Tiempo (seg:mseg)

100.000

3,141 _ _ _

0,000 _ _ _

1.000.000

3,141 _ _ _

0,000 _ _ _

10.000.000

3,141 _ _ _

0,000 _ _ _

100.000.000

3,141 _ _ _

0,000 _ _ _

1.000.000.000

3,141 _ _ _

0,000 _ _ _

Tabla-2. Tiempos de la versin piDos (error respecto de PI = 3.141592653590)


# Iteraciones

PI

Cota del Error

Tiempo (seg:mseg)

3,14159 _ _ _ _ _

0.000001

3,14159 _ _ _ _ _

0.0000001

3,14159 _ _ _ _ _

0.00000001

3,14159 _ _ _ _ _

0.000000001

3,14159 _ _ _ _ _

0.0000000001

Tabla-3. Tiempos de la versin piTres (error respecto de piAnterior)


# Iteraciones

PI

Error

Cota del Error

T. (seg:mseg)

3,138 _ _ _

0,002 _ _ _ 0.00001

3,141 _ _ _

0,000 _ _ _ 0.000001

3,141 _ _ _

0,000 _ _ _ 0.0000001

3,141 _ _ _

0,000 _ _ _ 0.00000001

3,141 _ _ _

0,000 _ _ _ 0.000000001

2. APLICACIN UTILIZANDO PThreads


Se utilizar una versin ligeramente modificada del programa piUno.c, llamada pi.c,
para tomar nuevamente tiempos de la ejecucin de la versin secuencial controlada por
un cierto nmero de iteraciones.

Programa pi.c
// pi.c: Programa que calcula el numero PI mediante el metodo de
//
Monte Carlo basado en circulo de radio 1 inscrito en
//
cuadrado de lado 2. Version secuencial.
//-----------------------------------------------------------------#include
#include
#include
#include

<assert.h>
<stdio.h>
<stdlib.h>
<sys/time.h>

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


int dentro, i, veces;
unsigned short xi[3];
double x, y;
struct timeval t0, t1, t;
assert (gettimeofday (&t0, NULL) == 0);
if (argc != 4) {
printf ("Uso: pi numVeces sed1 sed2\n");
return 0;
}
veces = atoi(argv[1]);
dentro = 0;
xi[0] = atoi(argv[2]);
xi[1] = atoi(argv[3]);
xi[2] = 0;
for (i=0; i<veces; i++) {
x = erand48(xi);
y = erand48(xi);
if (x*x+y*y <= 1.0) dentro++;
}
assert (gettimeofday (&t1, NULL) == 0);
timersub(&t1, &t0, &t);
printf ("Tiempo = %3ld:%3ld (seg:miliseg)\n", t.tv_sec,
t.tv_usec/1000);
printf ("Valor estimado de pi: %7.5f\n", 4.0*dentro/veces);
return 0;
}

Para la realizacin de esta parte del examen, hacer lo siguiente:


Entrar al equipo y situarse en el directorio correspondiente asociado a este
examen
Generar el ejecutable de la versin secuencial del clculo de pi
Ejecutarlo para 500 millones de iteraciones y semillas 3 y 4: pi 500000000 3 4.
Se recomienda hacer uso del script ocupar. Anotar el tiempo en la tabla
siguiente:

Tabla Res. PI con 500.000.000 y semilla 3 4


Programa

Con 2 procesos
seg:mseg

Eficiencia

Con 4 procesos
seg:mseg

Eficiencia

pi
piThreads

ASPECTOS DEL EXAMEN


Realizar todos los programas de manera individual y reportar el funcionamiento
de los mismos y el llenado de la tabla, entregando en formato electrnico los
resultados (pantallas de corrida) y la explicacin correspondiente.
Generar el ejecutable de la versin paralela basada en threads para cada uno de
los programas anteriores
Ejecutarlo con los mismos parmetros que en el caso secuencial, utilizando dos
procesos: piThreads 500000000 2 3 4. Anotar el tiempo en la Tabla.
Hacer lo mismo para cuatro procesos.
Reportar los resultados de las tablas en formato grfico

Vous aimerez peut-être aussi