You are on page 1of 13

Ind|ce

1.- Introduccin ................................................................................................................................................ 1


2.- Desarrollo ..................................................................................................................................................... 1
2.1.- Programa Secuencial ........................................................................................................................... 1
2.1.1.- PrintMat .......................................................................................................................................... 1
2.1.2.- CopyMat ......................................................................................................................................... 1
2.1.3.- CountNeighbours ........................................................................................................................... 2
2.1.4.- GameOfLive ................................................................................................................................... 2
2.1.5.- InitMatrix ....................................................................................................................................... 2
2.1.6.- Main ............................................................................................................................................... 3
2.2.- OpenMP ................................................................................................................................................ 3
2.2.1.- CopyMat ......................................................................................................................................... 3
2.2.2.- GameOfLive ................................................................................................................................... 3
2.2.3.- Main ............................................................................................................................................... 4
2.3.- MPI ....................................................................................................................................................... 4
2.3.1.- CopyMat ......................................................................................................................................... 4
2.3.2.- CountNeighbours ........................................................................................................................... 4
2.3.3.- GameOfLife ................................................................................................................................... 5
2.3.4.- FillExtended ................................................................................................................................... 5
2.3.5.- Main ............................................................................................................................................... 5
3.- Resultados .................................................................................................................................................... 7
3.1.- Secuencial ............................................................................................................................................. 7
3.2.- OpenMP ................................................................................................................................................ 8
3.3.- MPI ....................................................................................................................................................... 9
4.- Conclusiones .............................................................................................................................................. 11
5.- Anexo: Indicaciones de compilacin y ejecucin ................................................................................... 12
5.1.- Secuencial ........................................................................................................................................... 12
5.2.- OpenMP .............................................................................................................................................. 12
5.3.- MPI ..................................................................................................................................................... 12

Introduccin a la Computacin Paralela Mster SIANI

Pgina 1
1.- Introducc|n
El presente trabajo constituye la entrega del trabajo de curso de la asignatura Introduccin a la
Computacin Paralela, del Mster Universitario en Sistemas Inteligentes y Aplicaciones Numricas en la
Ingeniera. Consiste en la implementacin del Juego de la Vida de Conway de forma secuencial y paralela.
Esta ltima se realiza haciendo uso de las libreras OpenMP y MPI.
Dado que se trata de un problema clsico, en esta memoria se obviar la explicacin del mismo. Tambin,
ya que los conceptos fundamentales de las citadas libreras se han visto en clase, no se har descripcin
alguna de las mismas, salvo que fuera necesario en alguna parte de la solucin desarrollada. De esta forma,
en las siguientes secciones se ver: en la parte de desarrollo se describir la solucin adoptada, tanto para la
versin secuencial como para las versiones paralelas. En el apartado de resultados se vern cules son las
salidas que se han obtenido, considerando que se han hecho simulaciones para diferentes tamaos del grid y
diferentes configuraciones en las versiones paralelas. Por ltimo, en la seccin de conclusiones, se har un
anlisis de los resultados que se han obtenido.
2.- Desarro||o
En esta seccin se describir la solucin implementada, tanto su versin secuencial como las versiones
paralelas. Inicialmente se describir la primera, para posteriormente indicar cules han sido las
modificaciones necesarias para la obtencin de las otras dos. En principio, este proceso es casi trivial en el
caso de OpenMP, mientras que en el caso de MPI es preciso realizar un mayor nmero de cambios.
2.1.- rograma Secuenc|a|
Una de las consideraciones previas que se deben tener al comenzar es decidir si se va a hacer o no un
tratamiento toroidal del grid. Aunque en las primeras fases, por simplicidad, se tom la decisin de no
hacerlo, finalmente se ha incorporado esta funcionalidad. El tratamiento que se realiza en este sentido es
igual tanto en este caso, el secuencial, como en la implementacin en OpenMP. Sin embargo, en el caso del
desarrollo en MPI, se han hecho ligeros cambios, los cules sern descritos en el apartado 2.3.
La implementacin est compuesta por un conjunto de funciones. Es por ello que en los siguientes
apartados se va a tratar de describir todas y cada una de ellas, en el mismo orden en el que se pueden
encontrar en el fichero correspondiente. Dicho archivo es el denominado como sequential.cpp.
2.1.1.- r|ntMat
Este procedimiento es el encargado de imprimir en un fichero el resultado de las sucesivas iteraciones.
Para ello se hace uso de la librera fstream de C++ para el tratamiento de ficheros. Recibe como parmetros
un puntero al vector que representa el grid y la dimensin del mismo.
Dependiendo de la dimensin del grid, se crea un fichero que comienza por output_grid_X donde X es
el tamao de la matriz. El fichero siempre se abre en modo adicin, de forma que si este ya existe, el
resultado se aadir al final del mismo.
Dentro del fichero se representa la matriz donde cada posicin est asociada a un smbolo. Si el elemento
est vivo, es decir, su valor es 1, se escribir en el fichero un asterisco *. Sin embargo, si est muerta, se
escribir un punto .
Al terminar, se deja un espacio doble. De esta manera es sencillo diferenciar entre una iteracin y la
siguiente.
2.1.2.- CopyMat
Este procedimiento se ocupa de copiar una matriz en otra. Debido a que el proceso va escribiendo en la
posicin asociada de la matriz, siempre se tiene una copia del resultado de la iteracin anterior para realizar
la actualizacin. Recibe como parmetros dos punteros uno al vector de la matriz y otro a la copia, adems
del tamao.
Introduccin a la Computacin Paralela Mster SIANI

Pgina 2
Una vez terminada la iteracin se invoca a CopyMat para que actualice la matriz y as pasar a la siguiente
iteracin.
2.1.3.- CountNe|ghbours
Esta funcin es la encargada del conteo de los vecinos de una posicin dada, usando la vecindad de
Moore, es decir, sus ocho vecinos. Para ello se actualizan en cada caso los valores de ocho variables que
representan las ocho diferentes posiciones: esquina superior izquierda, borde superior, esquina superior
derecha, borde izquierdo, borde derecho, esquina inferior izquierda, borde inferior y esquina inferior derecha.
Recibe como parmetros el puntero al vector, la posicin (i,j) y el tamao.
En primer lugar se tiene en cuenta el caso general, es decir, que se est dentro de la matriz. Para ello los
ndices (i,j) de la posicin indicada han de ser ambos mayores que cero e inferiores a la dimensin de la
matriz.
Si no es as, se comienza a chequear si estamos en alguno de los casos descritos anteriormente: las cuatro
esquinas o los cuatro bordes. En cada uno de dichos casos se actualiza adecuadamente el valor que se ha de
coger del vecino adecuado, accediendo a la posicin correcta del vector que representa el grid. Un ejemplo
de este procedimiento puede verse en la ilustracin 1.
(n-1,n-1) (n-1,0) (n-1,1)



(0,n-1) (0,0) (0,1)
(1,n-1) (1,0) (1,1)

Ilustracin 1: ejemplo de tratamiento toroidal para la esquina superior izquierda. En azul el elemento a tratar, en verde sus
vecinos adyacentes y en rojo sus vecinos toroidales
Finalmente se devuelve el valor correspondiente a la suma de los valores de esos ocho vecinos ya que
cada uno de ellos slo puede valor cero o uno, en funcin de si est muerto o vivo respectivamente.
2.1.4.- GameCfL|ve
Este procedimiento es el encargado de realizar el Juego de la Vida de Conway. Para ello recibe por
parmetro el puntero a la matriz, la copia de la misma que es la que se actualiza y el tamao.
Simplemente se recorre toda la matriz y va invocando a la funcin anterior, CountNeighbours, para saber
cundo actualizar o no el valor asociado a cada posicin.
La actualizacin se realiza mediante una operacin a nivel de bits:
copy[i*size+j] = (NumNeighbours == 3) | (NumNeighbours==2 & m[i*size+j]);
Esta operacin permite hacer la actualizacin de una manera correcta y simple.
2.1.S.- In|tMatr|x
Este procedimiento se encarga de la inicializacin de la matriz. Recibe un puntero al vector y el tamao.
Es dependiente de una macro denominada RAND_INIT. En funcin de si esta macro vale uno o cero, se
proceder a hacer una inicializacin aleatoria o una conocida para hacer pruebas. Esta configuracin
predeterminada es la que se muestra en el enunciado de la prctica y es la usada siempre para saber si todo
est funcionando correctamente.
Introduccin a la Computacin Paralela Mster SIANI

Pgina 3
Los valores a cero representan que la clula o elemento en cuestin est muerto y el valor uno que est
vivo. En el caso de la inicializacin aleatoria se hace uso de la funcin rand() de C++ a la que se le aplica un
mdulo dos, para as siempre obtener como resultado valores cero o uno.
2.1.6.- Ma|n
Es el programa principal. En este caso no recibe ningn tipo de parmetro.
Inicialmente se tienen dos punteros, uno para la matriz y la copia de la misma. Luego se tienen dos
vectores para las pruebas. El primero de ellos es para diferentes tamaos del grid: diez, cincuenta, cien,
doscientos cincuenta, quinientos y mil. Este tamao se refiere a la longitud del lado, es decir, las matrices
sern de diez por diez y as sucesivamente. El otro vector es para el nmero de iteraciones: quinientas y mil.
Adems de estas variables se tienen dos ms para el cmputo del tiempo al principio y al final, para saber
cunto tarda la ejecucin.
Terminada la declaracin de variables, se tienen dos bucles anidados, uno para iterar en el vector de
tamaos de grid y el otro sobre el nmero de iteraciones. De esa forma se pueden hacer de manera
automtica las distintas pruebas.
A continuacin se reserva la memoria tanto para el grid principal como para la copia del mismo.
Recordemos que esto se hace as porque en el proceso del Juego de la Vida se va cambiando la matriz y se ha
de tener una copia en sobre la que ir mirando las vecindades de los elementos que se van a actualizar. Una
vez se ha cogido la memoria, se inicializa el vector y se obtiene el valor para la variable inicial del tiempo.
Se hace la primera copia del array y se comienzan las iteraciones.
En cada una de las iteraciones, si no se est computando el tiempo (macro COMPUTE_TIME a cero) se realiza
la impresin del grid invocando al procedimiento PrintMat, para ir viendo el proceso en un fichero.
Realmente el tiempo se computa siempre y esta macro slo sirve para determinar si se escribe o no en el
fichero de salida. Obviamente, adems de dicha impresin, en cada iteracin se invoca al procedimiento
GameOfLive anteriormente descrito.
Una vez finaliza el bucle se determina el tiempo final. Posteriormente, se imprime el ltimo estado del
grid (teniendo en cuenta el valor de COMPUTE_TIME) y se muestra por pantalla un mensaje que indica el tamao
del grid, las iteraciones realizadas y el tiempo transcurrido en dicha operacin.
Antes de pasar al siguiente valor para las iteraciones o tamao, se libera la memoria alojada para el vector
principal y la copia del mismo.
2.2.- CpenM
La paralelizacin del cdigo usando la librera OpenMP es casi inmediata. Simplemente es necesario para
empezar incluir la librera omp.h. La solucin en la que se ha usado OpenMP se encuentra en el fichero
openmp.cpp.
En el proceso de paralelizacin del cdigo es preciso tener en cuenta que oportunidades de procesamiento
paralelo se tienen en l. En nuestro desarrollo se encuentran principalmente dos: una de ellas es en el proceso
del Juego de la Vida y la otra en la copia del vector principal en un vector soporte.
2.2.1.- CopyMat
Ya que se trata de un bucle, simplemente es necesaria aadir la directiva de paralelizacin de un bucle
para que OpenMP lo procese. Es decir:
#pragma omp parallel for
for(int i=0; i<size*size; i++)
{
copy[i] = m[i];
}
2.2.2.- GameCfL|ve
En este caso se tienen dos bucles anidados. Se ha tomado la decisin de poner la directiva en el bucle ms
externo, declarando como variable privada el contador del bucle interno y que as no sea cambiado por todos
Introduccin a la Computacin Paralela Mster SIANI

Pgina 4
los hilos pudiendo causar esto un mal resultado. No se ha realizado una inversin de bucles, ya que esto
puede causar ms fallos de cach y, por tanto, una reduccin de rendimiento. El cdigo quedara como:
#pragma omp parallel for private(j)
for(int i = 0; i<size; i++)
{
for(j = 0; j<size; j++)
{
int NumNeighbours = CountNeighbours(m,i,j,size);
copy[i*size+j] = (NumNeighbours == 3) | (NumNeighbours==2 & m[i*size+j]);

}
}
Podra considerarse que, a parte de estas dos oportunidades de paralelizacin, existiera una tercera en la
funcin que se ocupa de la escritura en fichero. Pero como esta funcin no se ejecuta cuando se estn
realizando las pruebas, no tiene inters alguno en esto caso paralelizarla.
2.2.3.- Ma|n
Tambin se han realizado algunos cambios en el programa principal. Se ha aadido una nueva variable al
principio. Se trata de un vector en el que se indican el nmero de hilos que se van a lanzar, que sern iguales
al nmero de procesadores que se van a usar en las pruebas con MPI: dos, cinco y diez.
Por ello, ahora no se tienen slo los dos bucles relativos al tamao y el nmero de iteraciones, si no que
adems se tiene un tercer bucle anidado referente al nmero de hilos que se usan en la ejecucin OpenMP (el
bucle ms externo).
Las variables para el clculo del tiempo han pasado a ser de tipo double, usndose para la estimacin la
funcin omp_get_wtime() de OpenMP.
El resto de cdigo sigue siendo prcticamente el mismo que en la versin secuencial.
2.3.- MI
A diferencia del caso anterior, en el caso de MPI si hay que hacer algunos cambios ms, ya que ahora no
se hace uso de directivas, si no de funciones de la propia librera. Es tarea del programador dividir
adecuadamente el problema para que sea solucionado por cada uno de los procesadores. El fichero en el que
se encuentra esta solucin es el denominado mpi.cpp. Es necesario, al igual que antes, incluir la librera de
MPI, mpi.h.
Como se ha hecho en las secciones anteriores, se describirn los cambios hechos en cada una de las
funciones que hayan sido modificadas.
En esta versin adems de las macros COMPUTE_TIME y RAND_INIT (de escritura en fichero y tipo de
inicializacin respectivamente) se tiene una ms, DEBUG, para mostrar mensajes de depuracin si es preciso.
2.3.1.- CopyMat
En las anteriores versiones de esta funcin, el tamao size pasado se refera a una de las dimensiones del
grid, de forma que luego se recorra el vector hasta el tamao size*size. Sin embargo, como en MPI vamos a
tener tamaos variables de diferentes zonas del grid, el tamao que ahora se le pasa a la funcin es el
correspondiente a todo el trozo de vector directamente y no slo el referente a una dimensin. Es as que
ahora el lmite superior del bucle es directamente size.
2.3.2.- CountNe|ghbours
Se sigue la misma filosofa que en las implementaciones anteriores, salvo que ahora hay algunos
controles que no se hacen. Al igual que antes, se sigue teniendo en cuenta el caso en el que se est
explorando el interior de la matriz y tambin se tiene en cuenta que se est en lo que representara la primera
columna o la ltima. Sin embargo, se ha quitado todo el tratamiento de las esquinas y de los bordes superior
e inferior. Esto es as porque ahora en cada trozo de matriz que se vaya a tratar, existir una copia de la fila
inmediatamente superior e inferior al trozo que se tiene. De esta manera, no habr riesgo de salirse por esas
regiones.
Introduccin a la Computacin Paralela Mster SIANI

Pgina 5
Sobre cmo se divide el grid se hablar ms en produndidad en la seccin 2.3.5.
2.3.3.- GameCfL|fe
La diferencia ms significativa en este procedimiento es que ahora no se recorre la altura del grid por
completo, si no desde uno hasta height-1, por la razn que se ha dicho en la operacin anterior. El resto de su
cdigo sigue siendo igual salvo que ahora a la funcin de contar los vecinos, ya que slo se hacen
comprobaciones en el ancho del grid, se le pasa como tamao la variable width.
2.3.4.- I|||Lxtended
Este procedimiento es nuevo. Debido a que siempre se tratar que cada trozo de la matriz vaya
acompaado de la fila anterior y la siguiente, se crey necesario tener una funcin encargada de crear una
versin extendida tanto del grid original como de la copia del mismo. Este procedimiento hace esa labor
rellenando el interior del vector con los mismos valores que las originales y en aquellas posiciones que
representan la fila extra superior y la fila extra inferior del grid, se ponen los valores de la ltima fila y la
primera respectivamente. A estas filas se les ha denominado como phantom rows o filas fantasma. En la
ilustracin 2 se puede ver una representacin grfica.

Ilustracin 2: grid con sus filas fantasma
2.3.S.- Ma|n
En el programa principal es donde se ha hecho el mayor nmero de cambios. Se ha tratado de seguir el
mismo estilo con los vectores de tamao e iteraciones, aunque ahora mismo cada uno de ellos tiene un solo
valor. Cuando se quiere hacer una nueva prueba, simplemente es necesario cambiar cualquiera de estos dos
valores.
Adems de los dos punteros para el grid original y su copia, se tienen dos ms para sus versiones
extendidas, de las cuales se ha hablado anteriormente.
Ha de tenerse en cuenta que ya que se est usando C++, las operaciones de MPI usadas son las
equivalentes para este lenguaje, ya que la librera est disponible para varios de ellos. Inicialmente se
inicializa MPI y se obtiene el identificador del procesador, as como el nmero de procesadores existentes.
Tras ello, se computa el tamao del trozo que se va a mandar a cada procesador, en concreto lo que
representara la altura de dicho trozo (chunksize, vase chunksize en la ilustracin 3). Ntese que se ha
supuesto de entrada que el alto del grid es totalmente divisible entre el nmero de procesadores.
Con este conjunto de operaciones previas realizadas, se inicializa el contador de tiempo y empieza al
proceso. Si se trata del procesador master (el que tiene el identificador cero) se comienza por tomar memoria
para el grid, la copia, las versiones extendidas, un vector de tamaos de los trozos, otro de desplazamientos y
dos buffers locales, uno para el trozo en si y otro para su copia. Despus se pasa a inicializar el vector, hacer
la copia y rellenar las versiones extendidas. Tras ello se rellenan los vectores de tamaos y desplazamientos.
El tamao que se va a retransmitir siempre ser (chunksize+2)*size, es decir, la altura del trozo ms las dos
filas extra por el ancho de esas filas (vase ilustracin 3). En relacin a los desplazamientos, para el primer
trozo ser cero, mientras para los restantes ser el equivalente al rea ocupada por un trozo bsico, es decir,
Introduccin a la Computacin Paralela Mster SIANI

Pgina 6
sin las dos filas extra, multiplicado adems por el ndice del bucle. Se parte del trozo bsico para este
cmputo puesto que siempre se ha de dejar la ltima fila del trozo para ser enviada como primera fila
fantasma de la siguiente porcin de grid. En el caso de no ser el procesador master, simplemente se coge
memoria para los buffers locales.
Una vez se tienen las inicializaciones, se pasa al bucle de las iteraciones. En primer lugar, si se trata del
procesador master y no est activa la macro COMPUTE_TIME se imprime el estado del grid. A continuacin se
realiza la reparticin entre todos los procesadores usando la operacin Scatterv. A sta se le indica que se va
a repartir partiendo de la versin extendida, con los tamaos indicados en el vector de tamaos y los
desplazamientos del vector correspondiente. Se transmiten valores enteros y sern recibidos en el buffer
local, cuyo tamao es el indicado anteriormente (chunksize+2)*size. Este buffer ser tambin de valores
enteros.

Ilustracin 3: divisin por procesador suponiendo un tamao de grid 9 y 3 procesadores
Tras ello, se hace una copia del buffer local a su copia y se invoca a GameOfLive para ejecutar el Juego
de la Vida de Conway con el trozo actual. El ancho indicado ser size y el alto chunksize+2.
A continuacin, si se trata del procesador master, se hace un envo del resultado del Juego de la Vida,
usando la funcin Send de MPI. Tngase en cuenta que en todos los envos no se enva el buffer entero, si no
que se obvian la primera y ltima fila, ya que el resultado slo se encuentra en la regin restante. Es por ello
que el buffer en el envo se desplaza un tamao size y que el tamao a enviar es directamente chunksize*size,
dejndose as la ltima fila.
Posteriormente, para todos los procesadores, el master recibir los resultados mediante el mtodo Recv,
que recibe de forma estndar en modo bloqueante. Hay que tener en cuenta que la recepcin se hace sobre la
copia del grid. La direccin inicial va siendo desplazada en funcin del procesador del que se recibe y del
tamao de cada trozo.
En el caso de no estarse en el master, simplemente se hace el envo del resultado de la misma forma que
se ha indicado antes.
Despus se actualiza el grid principal con el resultado almacenado en la copia y se actualizan tambin las
extendidas. Con ello terminara el bucle de iteraciones. Tras salir de l, si se est en el master y no se
encuentra activa la macro indicada antes, se procede a imprimir el que sera el estado final del grid. Para
terminar se obtiene nuevamente el tiempo. En el caso, nuevamente, de estar en el master, se imprime por
pantalla el resultado obtenido, indicndose el tamao del grid, el nmero de iteraciones, el nmero de
procesadores y el tiempo transcurrido. Por ltimo se finaliza MPI.

Introduccin a la Computacin Paralela Mster SIANI

Pgina 7
3.- kesu|tados
En esta seccin se describen los resultados obtenidos para las tres implementaciones desarrolladas as
como las mejoras que se observan entre ellas.
3.1.- Secuenc|a|
En la ilustracin 4 se puede observar la simulacin del algoritmo secuencial para tamaos de grid 10, 50,
100, 250, 500 y 1000. A la izquierda la grfica corresponde a la ejecucin de 500 iteraciones en cada
configuracin y a la derecha de 1000 iteraciones.
500 Iteraciones

1000 Iteraciones
Tamao Tiempo(seg)

Tamao Tiempo(seg)
10 0,002389

10 0,004010
50 0,047925

50 0,095646
100 0,191376

100 0,382236
250 1,189310 250 2,377760
500 4,750750

500 9,511800
1000 19,209300

1000 38,386500
Tabla 1: resultados de la implementacin secuencial

Ilustracin 4: implementacin secuencial para tamaos 10, 50, 100, 250, 500 y 1000. A la izquierda 500 iteraciones y a la
derecha 1000
Puede observarse como el tiempo de ejecucin permanece estable hasta un tamao de grid de 100x100.
En cuanto se pasa tamaos superiores el tiempo aumenta de forma significativa. Obviamente, este aumento
es superior en los experimentos en los que se ejecutan mil iteraciones, llegndose a alcanzar los 38 segundos
para un grid de 1000x1000 elementos.

Introduccin a la Computacin Paralela Mster SIANI

Pgina 8
3.2.- CpenM
En la ilustracin 5 se muestran los resultados de simular en la implementacin OpenMP con tamaos de
grid de 10, 50, 100, 250, 500 y 1000, usando 2, 5 y 10 hilos. En la grfica de la izquierda se representan los
experimentos en los que se han ejecutado 500 iteraciones y a la derecha 1000.
500 Iteraciones
Tamao OMP2(seg) OMP5(seg) OMP10(seg)
10 0,022084 0,0343311 0,021143
50 0,0470359 0,048281 0,047272
100 0,125776 0,132642 0,128779
250 0,693114 0,690712 0,684054
500 2,8273 2,75767 2,69044
1000 11,1124 10,6826 11,0304
Tabla 2: resultados implementacin OpenMP 500 iteraciones
1000 Iteraciones
Tamao OMP2(seg) OMP5(seg) OMP10(seg)
10 0,042707 0,0639539 0,042717
50 0,0942791 0,0958819 0,0946531
100 0,249386 0,308115 0,250017
250 1,37422 1,35994 1,36421
500 5,95425 5,23784 5,28778
1000 22,8925 22,6414 22,3838
Tabla 3: resultados implementacin OpenMP 1000 iteraciones

Ilustracin 5: implementacin OpenMP para tamaos de grid de 10, 50, 100, 250, 500 y 1000, usando 2, 5 y 10 hilos. A la
izquierda 500 iteraciones y a la derecha 1000
Al igual que sucediera con el cdigo secuencial, existe cierta estabilidad hasta el grid de tamao 100x100
tanto en 500 como en 1000 iteraciones. A partir de ese tamao el tiempo de ejecucin aumenta, siendo
mayor en el caso de la ejecucin de 1000 iteraciones. No obstante, hay una ganancia significativa en tiempo
en comparacin con la implementacin anterior, ya que en el peor de los casos (grid de 1000x1000 con 1000
iteraciones) la ejecucin tarda unos 22,38 segundos. Esto supone una reduccin de unos 16 segundos
respecto al mismo caso en la implementacin secuencial. A continuacin se muestra el clculo del Speedup
tanto para 500 como para 100 iteraciones.

Introduccin a la Computacin Paralela Mster SIANI

Pgina 9
Speedup 500
Tamao OMP2 OMP5 OMP10
10 0,108178 0,069587 0,112992
50 1,018902 0,992626 1,013813
100 1,521562 1,442800 1,486080
250 1,715893 1,721860 1,738620
500 1,680313 1,722740 1,765789
1000 1,728636 1,798185 1,741487
Tabla 4: Speedup 500 iteraciones OpenMP
Speedup promedio: OMP2 = 1,277551 OMP5 = 1,291299 OMP10 = 1,309796

Speedup 1000
Tamao OMP2 OMP5 OMP10
10 0,093895 0,064108 0,093873
50 1,014498 0,997539 1,010489
100 1,532708 1,240562 1,528840
250 1,730261 1,748430 1,742957
500 1,597480 1,815977 1,798826
1000 1,676815 1,695411 1,714923
Tabla 5: Speedup 1000 iteraciones OpenMP
Speedup promedio: OMP2 = 1,274276 OMP5 = 1,260337 OMP10 = 1,314984
Tanto en 500 como en 1000 iteraciones se puede observar que el Speedup promedio mejora en todos los
casos a la implementacin secuencial, correspondiendo la mayor mejora a aquella que usa un mayor nmero
de hilos. Donde nico se puede ver que el programa con OpenMP no mejora al secuencial es para tamaos
de matriz pequeos, en los que incluso la versin paralela parece ser ligeramente ms lenta que la secuencial,
dando un Speedup inferior a 1.
3.3.- MI
En la ilustracin 6 se representan los resultados de la ejecucin de la implementacin usando MPI para
grids de tamao 10, 50, 100 y 250, usando 2, 5 y 10 procesadores. En la grfica de la izquierda se muestran
los resultados para la ejecucin de 500 iteraciones y en la derecha para 1000.
500 Iteraciones
Tamao MPI2(seg) MPI5(seg) MPI10(seg)
10 0,00342512 0,0203719 0,03423
50 0,0483229 0,037904 0,0462348
100 0,175886 0,135032 0,275421
250 1,07531 0,810167 0,765726
Tabla 6: resultados implementacin MPI 500 iteraciones
1000 Iteraciones
Tamao MPI2(seg) MPI5(seg) MPI10(seg)
10 0,00826001 0,0158761 0,026705
50 0,091737 0,072882 0,103934
100 0,322796 0,272283 0,282494
250 1,9295 1,53234 1,67017
Tabla 7: resultados implementacin MPI 1000 iteraciones
Introduccin a la Computacin Paralela Mster SIANI

Pgina 10

Ilustracin 6: implementacin MPI para grids de tamao 10, 50, 100 y 250, usando 2, 5 y 10 procesadores. Al izquierda 500
iteraccines y a la derecha 1000
A diferencia de las dos implementaciones anteriores, en este caso no se encuentra tanta estabilidad en las
primeras configuraciones de grid, aunque esto tambin puede ser debido a que en este experimento se
exploran tamaos menores y se ve ms en detalle los tiempos para dichos tamaos. No obstante, se observa
que despus de 100x100 el tiempo de ejecucin aumenta significativamente, siendo ms evidente en la
configuracin en la que se usan dos procesadores.
Aunque en el caso de 250x250 para 500 iteraciones la configuracin con 10 procesadores da un tiempo
ligeramente menor, es la que usa 5 la que parece tener un comportamiento ms regular con tiempos
generalmente inferiores a las otras, tanto para 500 como para 1000 iteraciones.
Speedup 500
Tamao MPI2 MPI5 MPI10
10 0,697493 0,117269 0,069792
50 0,991765 1,264378 1,036556
100 1,088068 1,417264 0,694848
250 1,106015 1,467981 1,553179
Tabla 8: Speedup 500 iteraciones MPI
Speedup promedio: MPI2 = 0,970835 MPI5 = 1,066723 MPI10 = 0,838593

Speedup 1000
Tamao MPI2 MPI5 MPI10
10 0,485471 0,252580 0,150159
50 1,042610 1,312340 0,920225
100 1,184141 1,403818 1,353076
250 1,232319 1,551718 1,423663
Tabla 9: Speedup 1000 iteraciones MPI
Speedup promedio: MP2 = 0,986135 MPI5 = 1,130114 MPI10 = 0,961780
Al contrario que sucediese en la implementacin OpenMP, en MPI no parece que el Speedup promedio
mejore demasiado a la implementacin original secuencial, salvo en el caso del uso de 5 procesadores. No
obstante, la mejora obtenida en este caso, es inferior a cualquiera de las obtenidas para la implementacin
OpenMP. Tambin puede verse que, como sucediese en OpenMP, no existe ganancia para tamaos de grid
muy pequeos, ya que el valor del Speedup es inferior a 1.
Introduccin a la Computacin Paralela Mster SIANI

Pgina 11
4.- Conc|us|ones
En este trabajo se ha visto el proceso de implementacin del Juego de la Vida de Conway tanto
secuencialmente como dos versiones paralelas, una usando OpenMP y otra con MPI. Se ha descrito en
detalle el desarrollo de todas y cada una de ellas, as como las distintas pruebas que se han realizado con el
objetivo de ver si las implementaciones paralelas mejoran a la versin secuencial.
De forma general la implementacin en OpenMP ha mejorado en tiempo a la implementacin secuencial,
obteniendo un Speedup promedio que vara entre el 1,26 y el 1,31 veces ms rpido. Como se ha descrito
con anterioridad, esta mejora no se aprecia para tamaos de grid pequeos, en los que incluso se empeora.
En el caso de MPI la mejora no es tan apreciable. No existe gran diferencia entre usar 5 10 procesadores,
obtenindose un mejor Speedup promedio en el caso de 5, dando que es 1,13 veces mejor que la
implementacin secuencial. De igual forma, la mejora es poco apreciable para tamaos de grid pequeos.
En suma, las tcnicas de paralelizacin pueden ayudar sustancialmente a reducir el tiempo de ejecucin
de los programas, siempre que se puedan encontrar oportunidades de paralelismo claras en el cdigo. No
obstante, es preciso tomar en cuenta el esfuerzo que conlleva la realizacin del cdigo paralelo y la ganancia
que con este cambio se obtiene. En funcin de los resultados obtenidos y, considerando esto ltimo, quizs la
mejor opcin sea el uso de OpenMP, ya que apenas requiere de esfuerzo y de cambios en el cdigo,
permitiendo probar fcilmente si nuestro algoritmo mejora al ser paralelizado. En el caso de MPI se requiere
un mayor esfuerzo, puesto que hay que rehacer partes del cdigo, siendo la paralelizacin ms complicada
que en el caso de usar OpenMP. De hecho, puede observarse como en ocasiones la mejora obtenida con MPI
es inferior a la que se obtiene con OpenMP, lo que podra llevar a replantearse el uso de aquella librera.

Introduccin a la Computacin Paralela Mster SIANI

Pgina 12
S.- Anexo: Ind|cac|ones de comp||ac|n y e[ecuc|n
Todas las implementaciones han sido compiladas y ejecutadas desde consola. A continuacin se muestran
las instrucciones necesarias para la compilacin y ejecucin de las tres implementaciones desarrolladas para
el presente trabajo.
S.1.- Secuenc|a|
En el caso del programa secuencial la lnea de compilacin es:
g++ sequential.cpp o sequential
Para la ejecucin simplemente es necesario ejecutar ./sequential y el programa realizar todas las
pruebas mostrando por pantalla los resultados. Es preciso recordar que si se quiere que se imprima en fichero
la configuracin del grid, hay que desactivar la macro COMPUTE_TIME.
S.2.- CpenM
La compilacin de la versin OpenMP se realiza mediante la siguiente instruccin:
g++ -fopenmp o openmp openmp.cpp
Para la ejecucin, al igual que antes, simplemente es necesario hacer ./openmp y el sistema har todas las
pruebas que han sido descritas. Igualmente si se quiere que se imprima en fichero hay que desactivar la
macro mencionada anteriormente.
S.3.- MI
En el caso de la implementacin usando MPI la compilacin se realiza como:
mpic++ -o mpi mpi.cpp
De la misma forma slo es necesario ejecutar ./mpi para que el programa funcione. No obstante, como se
describi en la etapa de desarrollo, esto slo ejecuta una configuracin. Es decir, un tamao de grid con un
nmero de iteraciones determinado. Si se desea cambiarlo simplemente habra que cambiar el nmero que se
pasa a la funcin push_back de los vectores de tamao e iteraciones en el programa principal del cdigo. De
la misma forma que se ha dicho para las otras dos versiones, si se desea que el resultado aparezca en el
fichero hay que desactivar la macro COMPUTE_TIME. Adems esta implementacin cuenta con una macro DEBUG
que muestra por dnde va pasando la ejecucin indicando procesador, dimensiones del grid o funcin en la
que se encuentra.

You might also like