MPI (iniciales de Message Passing Interface)
MPI es una especificación para programación de paso de mensajes, que proporciona una librería de funciones para C, C++ o Fortran que son empleadas en los programas para comunicar datos entre procesos.
MPI es la primera librería de paso de mensajes estándar y portable, especificada por consenso por el MPI Forum, con unas 40 organizaciones participantes, como modelo que permita desarrollar programas que puedan ser migrados a diferentes computadores paralelos.
El primer estándar MPI 1.0 fue acabado y publicado en mayo 1994. El estándar ha sido actualizado desde entonces, estando actualmente en desarrollo el MPI 2.
Características de MPI:
La especificación detalla las funciones que se pueden utilizar, no el modo como se compilan y lanzan-ejecutan los programas, lo cual puede variar de una implementación a otra.
Siguiendo el modelo SPMD, el usuario escribirá su aplicación como un proceso secuencial del que se lanzarán varias instancias que cooperan entre sí.
Los procesos invocan diferentes funciones MPI que permiten
Cualquier programa paralelo con MPI puede implementarse con tan sólo 6 funciones, aunque hay muchas más funciones para aspectos avanzados. Todas ellas empiezan por MPI_ y obligan a que los programas MPI tengan #include "mpi.h"
Los programas MPI deben ser obligatoriamente inicializados y finalizados en MPI (MPI_Init, MPI_Finalize).
Los procesos en ejecución pueden saber cuántos procesos MPI forman parte de un grupo de procesos -communicator en la terminología MPI- (MPI_Comm_size) y qué número de orden -empezando por 0- tiene en ese grupo de procesos (MPI_Comm_rank).
Los mensajes punto a punto deben ser enviados explícitamente por el emisor y recibidos explícitamente por el receptor (más adelante se explicarán las operaciones de comunicación colectivas), para lo cual pueden emplearse dos funciones básicas (MPI_Send y MPI_Recv).
#include <mpi.h>
codigo_error = MPI_nombre( parámetros ... )
int MPI_Init ( int *argc , char ***argv )
Conjunto de procesos que se intercomunican. Por defecto podemos utilizar MPI_COMM_WORD , en cuyo caso el grupo de procesos es el conjunto de procesos lanzados conjuntamente para resolver un problema
MPI_Comm_rank ( MPI_Comm comm , int *rank)
MPI_Comm_size ( MPI_Comm comm , int *size)
int MPI_Finalize ( )
Un mensaje estará formado por un cierto número de elementos de un mismo tipo MPI.
Tipos MPI básicos:
MPI_CHAR | signed char |
MPI_SHORT | signed short int |
MPI_INT | signed int |
MPI_LONG | signed long int |
MPI_UNSIGNED_CHAR | unsigned char |
MPI_UNSIGNED_SHOT | unsigned short int |
MPI_UNSIGNED | unsigned int |
MPI_UNSIGNED_LONG | unsigned long int |
MPI_FLOAT | float |
MPI_DOUBLE | double |
MPI_LONG_DOUBLE | long double |
MPI_BYTE | |
MPI_PACKED |
Tipos MPI derivados: los construye el programador.
int MPI_Send ( void *posicion_de_memoria , int contador ,
MPI_Datatype tipo , int destino , int etiqueta ,
MPI_Comm comunicador )
int MPI_Recv ( void *posicion_de_memoria , int contador ,
MPI_Datatype tipo , int origen , int etiqueta,
MPI_Comm comunicador , MPI_Status *estado)
El receptor puede emplear MPI_ANY_TAG y/o MPI_ANY_SOURCE
#include <stdio.h> #include <mpi.h> int main(int argc, char *argv[]) { int rank, size; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); printf("Hola! Soy el %d de %d\n", rank, size); MPI_Finalize(); return 0; }
#include <stdio.h> #include <mpi.h> int main(int argc, char *argv[]) { MPI_Status status; int num, rank, size, tag, next, from; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); /* Usaremos una etiqueta arbitraria de valor 201. Calculamos el identificador (rango) del siguiente y del anterior, suponiendo un anillo */ tag = 201; next = (rank + 1) % size; from = (rank + size - 1) % size; /* En uno de los procesos, el "primario", preguntamos un parametro */ if (rank == 0) { printf("Introduce el numero de vueltas al anillo: "); scanf("%d", &num); printf("Proceso %d envia %d al proceso %d\n", rank, num, next); MPI_Send(&num, 1, MPI_INT, next, tag, MPI_COMM_WORLD); } /* Los procesos "pasan" el numero de vueltas que faltan. Cuando llega al proceso 0, se descuenta una vuelta. Cuando un proceso recibe un 0, lo pasa y termina. */ do { MPI_Recv(&num, 1, MPI_INT, from, tag, MPI_COMM_WORLD, &status); printf("Proceso %d ha recibido %d\n", rank, num); if (rank == 0) { --num; printf("Proceso 0 descuenta una vuelta\n"); } printf("Proceso %d envia %d al proceso %d\n", rank, num, next); MPI_Send(&num, 1, MPI_INT, next, tag, MPI_COMM_WORLD); } while (num > 0); printf("Proceso %d termina\n", rank); /* El proceso "primario debe esperar el ultimo envio del ultimo proceso antes de terminar */ if (rank == 0) MPI_Recv(&num, 1, MPI_INT, from, tag, MPI_COMM_WORLD, &status); MPI_Finalize(); return 0; }
LAM-MPI (LAM viene de Local Area Multicomputer) es una implementación libre de MPI. Es un simple pero poderoso entorno para ejecutar y monitorizar aplicaciones MPI sobre redes de ordenadores.
El sistema LAM-MPI está compuesto de tres partes
Las diferentes órdenes son explicadas con su manual mediante el correspondiente man
El usuario crea un fichero que indique las máquinas que vayan a formar parte del multicomputador virtual.
lamboot [-v ficherohosts]
Arranca LAM (el multicomputador virtual) en una máquina o en un conjunto de máquinas.
recon [-v ficherohosts]
Verifica que se puede arrancar LAM en una máquina o en un conjunto de máquinas.
lamnodes
muestra los nodos (procesadores) que forman parte del multicomputador virtual.
mpicc: es un "atajo" para ejecutar el compilador cc que además encuentra los ficheros "include" de MPI y enlaza con las librerías MPI necesarias.
ejemplo: mpicc -o programa programa.c
mpirun. Una aplicación MPI con el modelo SPM se lanza con una simple orden que indica cuántas instancias del programa se ejecutarán.
ejemplo: mpirun -np 4 programa
El estado de los diferentes procesos MPI y de los mensajes que se intercambian puede ser monitorizado en todo momento.
mpitask
muestra el estado de los procesos en ejecución.
mpimsg
muestra los mensajes que estén enviándose o que no hayan sido recibidos todavía.
lamclean [-v]
Elimina todos los procesos MPI lanzados por el usuario y que no hayan terminado.
lamhalt
Termina la sesión de LAM, eliminando el daemon lamd, y debe ser ejecutado cuando no se vaya a seguir trabajando con LAM-MPI.
Algunas páginas con contenidos similares
Introducción a MPI - U.Autónoma de Madrid : explicación bastante completa en HTML con aspectos de implementación de LAM-MPI
Algoritmos y Programación Paralela - U. Murcia - Programación en memoria distribuida: MPI : pantallazos de clase
Programación Distribuida y Paralela - U. Granada - Introducción a MPI : pantallazos de clase; algunos aspectos se refieren a la implementación MPICH
Curso de Programación en Paralelo con MPI - U. Sevilla : estilo pantallazos
Programación de Multicomputadores con MPI - UJI : pantallazos de clase, con explicación medianamente detallada
Programación de aplicaciones paralelas con MPI - Universidad del País Vasco - es de 1997, pero es texto completo y detallado
LAM/MPI Parallel Computing en http://www.lam-mpi.org
Curso tutorial de MPI en el NCSA - Introduction to MPI : (necesita registro, que es libre)
University of Notre Dame - MPI Tutorial