Message Passing Interface (MPI, interfaz de paso de mensajes) es una interfaz de programación ( API ) para la transferencia de información , que permite intercambiar mensajes entre procesos que realizan la misma tarea. Diseñado por William Groupe , Evin Lusk y otros.
MPI es el estándar de interfaz de intercambio de datos más común en la programación paralela y existen implementaciones para una gran cantidad de plataformas informáticas. Utilizado en el desarrollo de programas para clusters y supercomputadoras . El principal medio de comunicación entre procesos en MPI es el paso de mensajes entre sí.
MPI está estandarizado por el MPI Forum . El estándar MPI describe una interfaz de paso de mensajes que debe admitirse tanto en la plataforma como en las aplicaciones del usuario . Actualmente hay una gran cantidad de implementaciones gratuitas y comerciales de MPI. Hay implementaciones para Fortran 77/90, Java , C y C++ .
MPI está principalmente orientado a sistemas de memoria distribuida , es decir, cuando los costos de transferencia de datos son altos, mientras que OpenMP está orientado a sistemas de memoria compartida (multinúcleo con caché compartida). Ambas tecnologías se pueden usar juntas para hacer un uso óptimo de los sistemas multinúcleo en un clúster.
La primera versión de MPI se desarrolló en 1993-1994 y MPI 1 salió en 1994.
La mayoría de las implementaciones MPI modernas admiten la versión 1.1. El estándar MPI versión 2.0 es compatible con la mayoría de las implementaciones modernas; sin embargo, es posible que algunas características no estén completamente implementadas.
MPI 1.1 (publicado el 12 de junio de 1995 , implementado por primera vez en 2002) admite las siguientes características:
En MPI 2.0 (publicado el 18 de julio de 1997 ), se admiten adicionalmente las siguientes características:
MPI 2.1 se lanzó a principios de septiembre de 2008.
MPI 2.2 se lanzó el 4 de septiembre de 2009.
MPI 3.0 se lanzó el 21 de septiembre de 2012.
El mecanismo básico para la comunicación entre procesos MPI es la transmisión y recepción de mensajes. El mensaje lleva los datos transmitidos y la información que permite que el lado receptor los reciba selectivamente:
Las operaciones de envío y recepción pueden ser de bloqueo o de no bloqueo. Para las operaciones sin bloqueo, se definen las funciones de verificar la disponibilidad y esperar la ejecución de la operación.
Otro método de comunicación es el acceso a memoria remota (RMA), que permite leer y modificar el área de memoria de un proceso remoto. El proceso local puede transferir el área de memoria del proceso remoto (dentro de la ventana especificada por los procesos) a su memoria y viceversa, así como combinar los datos transferidos al proceso remoto con los datos disponibles en su memoria (por ejemplo , sumando). Todas las operaciones de acceso a memoria remota no son de bloqueo, sin embargo, las funciones de sincronización de bloqueo deben llamarse antes y después de que se realicen.
El siguiente es un ejemplo de un programa de cálculo de números C usando MPI :
// Incluir encabezados requeridos #include <stdio.h> #incluir <matemáticas.h> // Incluyendo el archivo de cabecera MPI #include "mpi.h" // Función para cálculos intermedios double f ( double a ) { retorno ( 4.0 / ( 1.0 + a * a )); } // Función del programa principal int main ( int argc , char ** argv ) { // Declaración de variables int done = 0 , n , myid , numprocs , i ; doble PI25DT = 3.141592653589793238462643 ; doble mypi , pi , h , sum , x ; tiempo de inicio doble = 0.0 , tiempo de fin ; nombre int ; char nombre_procesador [ MPI_MAX_PROCESSOR_NAME ]; // Inicializar el subsistema MPI MPI_Init ( & argc , & argv ); // Obtenga el tamaño del comunicador MPI_COMM_WORLD // (número total de procesos dentro de la tarea) MPI_Comm_size ( MPI_COMM_WORLD , & numprocs ); // Obtener el número del proceso actual dentro // del comunicador MPI_COMM_WORLD MPI_Comm_rank ( MPI_COMM_WORLD , & myid ); MPI_Get_processor_name ( processor_name , & namelen ); // Imprime el número de subproceso en el grupo compartido fprintf ( stdout , "El proceso %d de %d está en %s \n " , myid , numprocs , nombre_procesador ); fflush ( salida estándar ); mientras ( ! hecho ) { // número de intervalos if ( myid == 0 ) { fprintf ( stdout , "Ingrese el número de intervalos: (0 sale)" ); fflush ( salida estándar ); si ( scanf ( "%d" , & n ) != 1 ) { fprintf ( stdout , "No se ingresó ningún número; saliendo \n " ); norte = 0 _ } startwtime = MPI_Wtime (); } // Transmitir el número de intervalos a todos los procesos (incluidos nosotros mismos) MPI_Bcast ( & n , 1 , MPI_INT , 0 , MPI_COMM_WORLD ); si ( norte == 0 ) hecho = 1 ; más { h = 1.0 / ( doble ) n ; suma = 0.0 ; // Calcular el punto asignado al proceso para ( i = myid + 1 ; ( i <= n ) ; i += numprocs ) { x = h * (( doble ) i - 0.5 ); suma += f ( x ); } mypi = h * suma ; // Restablecer los resultados de todos los procesos y agregar MPI_Reduce ( & mypi , & pi , 1 , MPI_DOUBLE , MPI_SUM , 0 , MPI_COMM_WORLD ); // Si este es el proceso principal, imprime el resultado if ( myid == 0 ) { printf ( "PI es aproximadamente %.16lf, el error es %.16lf \n " , pi , fabs ( pi - PI25DT )); endwtime = MPI_Wtime (); printf ( "hora del reloj de pared =%lf \n " , horafinal - horainicial ); fflush ( salida estándar ); } } } // Liberar el subsistema MPI MPI_Finalize (); devolver 0 ; }distribuida y paralela | Software para computación|
---|---|
Normas, bibliotecas | |
Software de monitoreo | |
Software de control |