High Performance Computing Applications
Autor
Roig Rebato, AlbertFecha
2021Resumen
La ciencia computacional puede considerase ya el tercer pilar del m´etodo cient´ıfico. En los ´ultimos
a˜nos se han puesto muchos esfuerzos en mejorar el poder de c´omputo en las supercomputadoras.
Todas las computadoras se actualizan cada 3-4 a˜nos ofreciendo grandes novedades en el hardware.
Sin embargo, los c´odigos no se adaptan a estos cambios, de forma que no se le saca todo el rendimiento
que se podr´ıa.
Una de las formas de aumentar el poder de las supercomputadoras es el paralelismo masivo.
Un ordenador, o nodo, est´a formado por dos partes caracter´ısticas: el procesador (CPU), que se
encarga de ejecutar las instrucciones de los programas; y la memoria, que es donde se encuentran
todos los datos. Las supercomputadoras modernas consisten en miles de nodos conectados con
m´ultiples procesadores cada uno.
Generalmente se usan dos librer´ıas para la computaci´on en paralelo: OpenMP y MPI. Ambas
son implementables en C/C++ y Fortran. OpenMP es una API que permite paralelizar programas
en arquitecturas de memoria compartida (en multi-core nodes). Partes del programa se ejecutan
en un “hilo principal” (del ingl´es master thread), y otras en “hilos esclavos” (slave threads). Todos
los “hilos” comparten variables en la misma direcci´on de memoria, por tanto, pueden acceder y
modificarlas sin necesidad de comunicaci´on entre “hilos”.
MPI significa Message Passing Interface. Se trata de una librer´ıa para pasar datos de la direcci´on
de memoria de un proceso a otro proceso. El prop´osito de MPI es la comunicaci´on entre procesos
en arquitecturas de memoria distribuida, aunque tambi´en es implementable en memorias compartidas. Hay var´ıas formas de comunicaci´on entre nodos, a grandes rasgos podr´ıamos clasificarlas en
bidireccionales o unidireccionales.
La comunicaci´on bidireccional requiere funciones emparejadas para pasar informaci´on de un nodo
a otro. Es decir, requiere que en el c´odigo de ambos procesos haya un mensaje acorde; de env´ıo en
una direcci´on, y de recibo en la otra. Esto se puede de distintas maneras. Mediante comunicaci´on
punto a punto, o sea, dos procesos que se comunican. O mediante funciones colectivas, en la que la
comunicaci´on involucra a m´as de dos procesos.
Las ´ultimas versiones de MPI permiten usar funciones de Acceso Remoto de Memoria (Remote
Memory Access RMA) para obtener o transferir datos de otros nodos. Estas funciones permiten
crear una ventana de memoria compartida a la cu´al otros procesos pueden acceder. La ventaja
de este m´etodo es que permite transferencias de datos entre procesos sin necesidad de funciones
emparejadas (como un MPI_Send necesita un MPI_Recv), ahorrando la comunicaci´on entre ambas
partes, este m´etodo se conoce como comunicaci´on unidireccional (one-sided communication).
Una de las ventajas de OpenMP es que su implementaci´on es simple. La mayor desventaja es
que no se pude correr en arquitecturas de memoria distribuida. MPI tiene una implementaci´on m´as
complicada pero permite su ejecuci´on en cualquier arquitectura e, incluso, puede llegar a ser m´as
eficiente que OpenMP en memorias compartidas.
Los profilers se han convertido en una herramienta imprescindible para cualquier programador.
Un profiler se encarga de recoger informaci´on a lo largo de la ejecuci´on de un c´odigo. Por ejemplo,
la cantidad de memoria usada por el programa o, el tiempo que pasa en cada funci´on. En este
trabajo utilizamos Scalasca para realizar el an´alisis de rendimiento de software.
Este trabajo consta de dos partes claramente diferenciadas. En la primera parte, creamos un
c´odigo que resuelve el problema de N-cuerpos gravitacional mediante un m´etodo de integraci´on
directa de la segunda ley de Newton. De manera que es un algoritmo O(N(N − 1)), donde N es el
n´umero de part´ıculas. Calculamos la aceleraci´on, la velocidad y la posici´on de cada part´ıcula en cada
paso de tiempo. Dado que los c´alculos para cada part´ıcula son independientes a los c´alculos realizados
para las otras, el problema es altamente paralelizable. Se distribuir el c´alculo de las trayectorias de las
part´ıculas entre distintos procesador. Con el objetivo de probar los varios m´etodos de paralelizaci´on
comentados, paralelizaremos los c´alculos con OpenMP, MPI-punto a punto y MPI-RMA. El c´odigo
est´a escrito en Fortran 90.
La paralelizaci´on con OpenMP es relativamente simple. Utilizamos la directriz (en ingl´es directive) parallel do que permite especificar al compilador la parte de c´odigo que se desea paralelizar.
Tambi´en utilizamos la cl´ausula private para determinar qu´e variables deben o no ser compartidas
entre los “hilos”.
La paralelizaci´on con MPI requiere comunicaci´on entre procesos ya que las variables en cada uno
son privadas. Para el c´alculo de fuerzas se necesita la posici´on de todas las part´ıculas, sin embargo,
cada proceso calcula las posiciones de una fracci´on de ellas. Por lo tanto, los procesos deber´an
comunicarse para tener acceso a las posiciones actualizadas. La comunicaci´on MPI-punto a punto
se hace con el m´etodo del anillo, es decir, un proceso env´ıa datos al siguiente proceso y recibe del
anterior. La comunicaci´on entre procesos se realiza mediante las funciones: MPI_Isend y MPI_Irecv.
La particularidad de ´estas es que son funciones sin bloqueo (non-blocking functions).
Para la comunicaci´on MPI-RMA se utilizan las funciones MPI_Win_create y MPI_Get, con las
que se crea un espacio de memoria compartida y se accede a los espacios de los otros procesos,
respectivamente.
Medimos el tiempo de ejecuci´on en un ordenador de memoria compartida con tal de determinar
cu´al es el m´etodo con mejor rendimiento. El m´etodo MPI-RMA es el que da mejores resultados,
llegando a hacer el c´odigo 6.9 veces m´as r´apido cuando se usan 8 procesadores que cuando se corre
el c´odigo en serie. En segundo lugar, el m´etodo MPI-punto a punto que hace el c´odigo 6.7 veces
m´as r´apido para el mismo n´umero de procesadores. Finalmente OpenMP, consigue acelerar 6.1
veces el c´odigo con 8 procesadores.
La segunda parte consiste en la optimizaci´on de un c´odigo en serie que sintetiza l´ıneas espectrales.
Para ello implementamos m´etodos de HPC. En este art´ıculo solo nos centramos en la computaci´on,
la f´ısica no se discute. Lo primero que hacemos es un profile del c´odigo para encontrar posibles
puntos conflictivos (bottle-necks). Encontramos que un 56% del tiempo de ejecuci´on se pasa en
una funci´on. As´ı pues, nos centramos en la optimizaci´on de est´a funci´on. Se trata de un c´odigo
en Fortran 77 que utiliza funciones que est´an en desuso y deben ser actualizadas. Por ejemplo,
eliminamos los COMMON blocks ya que son m´etodo de organizar las variables muy conflictivo.
Finalmente, paralelizamos la funci´on en la que se encuentra el bottle-neck mediante OpenMP.
Obtenemos un c´odigo hasta 1.28 veces m´as r´apido cuando se ejecuta con 6 procesadores que
con el c´odigo en serie. Usando m´as procesadores el aumento de velocidad del c´odigo disminuye.
Concluimos que el uso ´optimo del c´odigo es ejecutarlo con 4 procesadores, alcanzando una ejecuci´on 1.27 veces m´as rpida.