domingo, 21 de noviembre de 2010

Programación de aplicaciones paralelas con MPI (Message Passing Interface)

MPI es, como su nombre indica, es un interfaz, lo que quiere decir que el
estándar no exige una determinada implementación del mismo. Lo
importante es dar al programador una colección de funciones para que ésterealize su aplicación, sin que tenga necesariamente que conocer el hardware
concreto sobre el que se va a ejecutar, ni la forma en la que se han
implementado las funciones que emplea.

MPI ha sido desarrollado por el MPI Forum, un grupo formado por
investigadores de universidades, laboratorios y empresas involucrados en la
computación de altas prestaciones.
Sus objetivos fundamentales del MPI
Forum son los siguientes:
1. Definir un entorno de programación único que garantice la portabilidad de
las aplicaciones paralelas.
2. Definir totalmente el interfaz de programación, sin especificar cómo debe
ser la implementación del mismo
3. Ofrecer implementaciones de calidad, de dominio público, para favorecer
la extensión del estándar.
4. Convencer a los fabricantes de computadores paralelos para que ofrezcan
versiones de MPI optimizadas para sus máquinas ( lo que ya han hecho
fabricantes como IBM y Silicon Graphics).
Los elementos básicos de MPI son una definición de un interfaz de
programación independiente de lenguajes, más una colección de bindings o
concreciones de ese interfaz para los lenguajes de programación más
extendidos en la comunidad usuaria de computadores paralelos:
C y FORTRAN.
Un programador que quiera emplear MPI para sus futuros proyectos trabajará con una implementación concreta de MPI, que constará de , al menos, estos
elementos:
• Una biblioteca de funciones para C, más el fichero de cabecera mpi.h con
las definiciones de esas funciones y de una colección de constantes y
macros.
• Una biblioteca de funciones para FORTRAN + mpif.h.
• Comandos para compilación, típicamente mpicc, mpif77, que son
versiones de los comandos de compilación habituales (cc, f77) que
incorporan automáticamente las bibliotecas MPI.
• Comandos para la ejecución de aplicaciones paralelas, típicamente
mpirun.
• Herramientas para monitorización y depuración.
MPI no es, evidentemente, el único entorno disponible para la elaboración de
aplicaciones paralelas. Existen muchas alternativas, entre las que
destacamos las siguientes:
• Utilizar las bibliotecas de programación propias del computador paralelo
disponible: NX en el Intel Paragon, MPL en el IBM SP2, etc.
• PVM (Parallel Virtual Machine): de características similares a MPI, se
desarrolló con la idea de hacer que una red de estaciones de trabajo
funcionase como un multicomputador. Funciona también en
multicomputadores, normalmente como una c apa de software encima del
mecanismo de comunicaciones nativo.
• Usar, si es posible, lenguajes de programación paralelos (FORTRAN 90) o
secuenciales (C, FORTRAN 77) con directivas de paralelismo.
• Usar lenguajes secuenciales junto con compiladores que paralelicen
automáticamente.
MPI está aún en sus comienzos, y aunque se está haciendo un hueco
creciente en la comunidad de programadores de aplicaciones científicas
paralelas, no es probable que desplace a corto plazo a los entornos de
programación ya existentes (como los anteriormente citados) o impida la
aparición de otros nuevos.

El MPI Forum es consciente de que MPI todavía
adolece de algunas limitaciones, e incluso ha identificado bastantes de ellas:

• Entrada/salida: no se establece un mecanismo estandarizado de E/S
paralela.
• Creación dinámica de procesos. MPI asume un número de procesos
constante, establecido al arrancar la aplicación.
• Variables compartidas. El modelo de comunicación estandarizado por MPI
sólo tiene en cuente el paso de mensajes.
• Bindings para otros lenguajes, además de C y FORTRAN. Se piensa, en
concreto, en C++ y Ada.
• Soporte para aplicaciones de tiempo real. MPI no recoge en ningún punto
restricciones de tiempo real.
• Interfaces gráficos. No se define ningún aspecto relacionado con la
interacción mediante GUIs con una aplicación paralela.

Como ya hemos comentado, MPI está especialmente diseñado para
desarrollar aplicaciones SPMD. Al arrancar una aplicación se lanzan en
paralelo N copias del mismo programa * (procesos). Estos procesos no
avanzan sincronizados instrucción a instrucción sino que la sincronización,
cuando sea necesaria, tiene que ser explícita. Los procesos tienen un
espacio de memoria completamente separado. El intercambio de
información, así como la sincronización, se hacen mediante paso de
mensajes.
Se dispone de funciones de comunicación punto a punto (que involucran sólo
a dos procesos), y de funciones u operaciones colectivas (que involucran a
mútiples procesos). Los procesos pueden agruparse y formar
comunicadores, lo que permite una definición del ámbito de las operaciones
colectivas, así como un diseño modular.
La estructura típica de un programa MPI, usando el binding para C, es la
siguiente:
# include "mpi.h"
main (int argc, char **argv) {
int nproc; /* Número de procesos */
int yo; /* Mi dirección: 0<=yo<=(nproc-1) */
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
MPI_Comm_rank(MPI_COMM_WORLD, &yo);
/* CUERPO DEL PROGRAMA */
}
MPI_Finalize();
Este segmento de código ya nos presenta cuatro de las funciones más
*
Las implementaciones de MPI también suelen permitir lanzar aplicaciones en las que no
todos los procesos ejecutan el mismo programa.
utilizadas de MPI: MPI_Init() para iniciar la aplicación paralela,
MPI_Comm_size() para averiguar el número de procesos que participan en
la aplicación, MPI_Comm_rank(), para que cada proceso averigue su
dirección (identificador) dentro de la colección de procesos que componen la
aplicación, y MPI_Finalize() para dar por finalizada la aplicación.

MPI_Init(int *argc, char ***argv);
MPI_Comm_size (MPI_Comm comm, int *size);
MPI_Comm_rank (MPI_Comm comm, int *rank);
MPI_Finalize(void);
El ejemplo nos sirve también para que prestemos atención a algunas
convenciones de MPI. Los nombres de todas las funciones empiezan con
“MPI_”, la primera letra que sigue siempre es mayúscula, y el resto son
minúsculas.
La mayor parte de las funciones MPI devuelven un entero, que es un
diagnóstico. Si el valor devuelto es MPI_SUCCESS, la función se ha
realizado con éxito. No se han estandarizado otros posibles valores.
La palabra clave MPI_COMM_WORLD hace referencia a l comunicador
universal, un comunicador predefinido por MPI que incluye a todos los
procesos de la aplicación. Más adelante veremos cómo definir otros
comunicadores. Todas las funciones de comunicación de MPI necesitan
como argumento un comunicador.
En el resto de este tutorial vamos a ir presentando las diferentes funciones
que MPI ofrece para la comunicación y sincronización entre procesos. En la
sección 2 presentamos los mecanismos para la comunicación entre pares de
procesos (Comunicación punto a punto). En la sección 3 presentamos las
funciones para comunicación entre grupos de procesos ( Operaciones
colectivas). La sección 4 discute aspectos de MPI relacionados con la
Modularidad. En la sección 5 se describen las funciones disponibles para
definir Tipos de datos derivados. Por último, la sección 6 (Bibliografía) aporta
referencias para la localización de información adicional sobre MPI.

1 comentario: