MPI
Principios Básicos

Example HR

Tópicos

Nota: Si se presentan problemas con las animaciones, haga "Reload" la página.


Example HR

¿Qué es MPI?

Es una librería de comunicaciones que puede ser utilizada desde programas escritos en lenguaje C o FORTRAN. Estos programas deben ser compilados con los compiladores ordinarios para estos lenguajes y enlazados con la librería de MPI.
MPI está basada en el modelo de pase de mensajes, i.e. un cálculo es una colección de procesos que se comunican a través de mensajes.
MPI representa un esfuerzo de la comunidad de programación paralela por estandarizar las subrutinas de comunicación en computadores de cómputo masivo.

Construyendo nuestro primer programa: hello.c

  1. Cada programa en MPI debe incluir la directiva de preprocesamiento:
  2. El archivo mpi.h contiene las definiciones y las declaraciones necesarias para compilar un programa que use la librería MPI.
  3. Todos los identificadores de MPI contienen el prefijo: MPI_
  4. Antes de llamar a cualquier función de MPI, es necesario invocar una sola vez a la primitiva MPI_Init. Esto produce ciertas inicializaciones que permiten que la librería sea utilizada.
  5. Cuando el programa ha dejado de utilizar la librería debe invocar a la primitiva MPI_Finalize. Esta llamada debe hacerla cada proceso envuelto en el cómputo.
  6. Para identificar un proceso se dispone de la función MPI_Comm_rank., en su segundo parámetro regresa la identificación del proceso. Su primer parámetro es un comunicador. Un comunicador identifica a un grupo de procesos que pueden enviarse mensajes entre sí, el comunicador por defecto es MPI_COMM_WORLD, que a todos los procesos que corren cuando comienza el programa.
  7. Para conocer el número de procesos asociados a un comunicador se utiliza la función MPI_Comm_size.

  8.  
  9. El pase de mensaje lo realizaremos con las primitivas MPI_Send y MPI_Recv.

Comunicaciones Punto a Punto

Las comunicaciones punto a punto se refieren a la transmisión de un mensaje desde el proceso que envía hacia el proceso que recibe. El modo de comunicación puede ser bloqueante o no bloqueante.

El modo de comunicación especifica cómo el sistema maneja el mensaje. Para realizar un send el programador puede escoger entre cuatro modos de comunicación: synchronous, ready, buffered y standard. En este módulo veremos el comportamiento de cada modo y discutiremos sus ventajas y desventajas.

Además de especificar el modo de comunicación, el programador debe decidir si las llamadas de send y receive son bloqueantes o no bloqueantes. Un send bloqueante o no bloqueante debe estar en correspondencia con un receive bloqueante o no bloqueante.

Un send o receive bloqueante suspende la ejecución del programa del usuario hasta que el buffer a ser enviado/recibido sea seguro para usar. un send o receive no bloqueante inicia la comunicación y luego regresa casi inmediatamente a seguir con la ejecución del programa del usuario. En este módulo veremos cómo este comportamiento tiene un impacto en los requerimientos de programación y en el desempeño del programa.

Modos de Comunicación

Los modos de comunicación especificados por el send son:
modo synchronous (el más seguro y el más portable)
modo ready (el que ocasiona menor overhead al sistema)
modo buffered (desacopla al que envía de quién recibe, permite que el usuario tenga el control)
modo standard (compromiso)
Blocking o non-blocking especificados por  send y receive

      blocking calls pueden estar en correspondencia con non-blocking calls
      blocking suspende la ejecución hasta que el  message buffer sea seguro de usar
      non-blocking inicia la comunicación

Comportamiento bloqueante.

Blocking Synchronous Send

Mediante este mecanismo (MPI_Ssend(...)) quien envía el mensaje no continúa con su trabajo hasta tanto el destinatario comienza a recibir el mensaje.

Cuando el  Blocking Synchronous Send se ejecuta, la tarea que hace el envío le indica al receptor que tiene un mensaje para él y espera a que el receptor le envíe un mensaje indicándole que está listo para recibir el mensaje. Entonces los datos son transferidos.

Aquí hay dos fuentes de overhead: el overhead del sistema (el trabajo que realiza el sistema para enviar el mensaje hacia la tarea destino: copiar el mensaje de la red al buffer de quien recibe) y el overhead de sincronización (el tiempo esperando para que ocurra un evento en la otra tarea).

Blocking Ready Send

Este mecanismo (MPI_Rsend(...)) permite al programador notificar al sistema que un receive ya ha sido invocado, por ello puede utilizar un protocolo más rápido si está disponible.

El MPI_Rsend envía un mensaje a través de la red. El requiere que haya llegado una notificación diciendo "estoy listo para recibir" enviada por una tarea que espera recibir. Si esa notificación no ha llegado entonces ocurre un error.


Blocking Buffered Send

El blocking Buffered Send (MPI_Bsend(...)) copia los datos desde el buffer de mensajes a un buffer dado por el usuario y luego retorna. Los datos serán copiados desde el buffer dado por el usuario a la red cuando se reciba una notificación diciendo "estoy listo para recibir".

Blocking Standard Send

En el  blocking standard send (MPI_Send (...))  se copia el mensaje sobre la red en el buffer del sistema del nodo que recibe, entonces la tarea que ejecuta el send continúa con su ejecución. El buffer del sistema es creado cuando comienza el programa (el usuario no necesita utilizarlo de ninguna manera). Hay un buffer del sistema por cada tarea que se encargará de manejar múltiples mensajes. El mensaje será copiado del buffer del sistema a la tarea que invoca el receive cuando se ejecute el receive.

Comportamiento No Bloqueante

Un send/receive bloqueante sustpende la ejecución del programa hasta que el buffer que se está enviando/recibiendo es seguro de usar. En el caso de un send bloqueante, esto significa que los datos a ser enviados han sido copiados en el buffer de envío (no necesariamente han sido recibidos por la tarea que recibe).

Las llamadas no bloqueantes terminan inmediatamente después de ser iniciada la comunicación. El programador no sabe si los datos han sido enviados o copiados en el buffer de envío o si los datos ha ser recibidos han llegado. Por ello, antes de utilizar el buffer de mensajes, el programador debe verificar su estátus.


Ejercicios

Ejercicio 1

Este ejercicio ayuda a visualizar  el desempeño relativo de los cuatro modos de comunicación  (synchronous, ready, buffered, y standard). El programa indica el tiempo (wallclock) empleado en llamadas bloqueantes para los cuatro modos de comunicación. Todos los receives son colocados antes que cualquier mensaje sea enviado, nótese que se obtendrían tiempos diferentes si los receives no se colocan así.
  1. Lea el programa
  2. Compílelo ? ejecútelo
  3. Note el tiempo empleado por el blocking send en los cuatro modos.
Código en C: blocksends.c
Código en FORTRAN: blocksends.f
 

Ejercicio 2

Este ejercicio permite constatar que las rutinas no bloqueantes son más seguras que las bloqueantes

Código en C: deadlock.c
Solución del programa en C: fixed.c
Código en FORTRAN: deadlock.f
Solución del programa en FORTRAN: fixed.f

  1. Compile el programa deadlock, ejecute el programa con dos procesos. El programa escribirá unas lineas y luego se detendrá. Aborte el programa con <ctrl>.
  2. ¿Entiende por qué el programa entra en interbloqueo?
  3. Corrija el programa de manera de evitar el interbloqueo
  4. Compare su solución con la dada.

Ejercicio 3

Este ejercicio demuestra que al reemplazar un blocking receive con un non-blocking receive puede reducirse el overhead de la sincronización en mensajes de tamaño mayor que 4K.
Brecv es un programa mal hecho en el que la tarea 0 realiza un blocking send, y la tarea 1 duerme por diez segundos antes de realizar el blocking receive. La llamada a dormir pretende simular el tiempo a emplear realizando cómputos útiles.

Código en C: brecv.c new_sleep.c
Solución del programa en C: nbrecv.cnew_sleep.c
Código en FORTRAN: brecv.f, new_sleep.c
Solución del programa en FORTRAN: nbrecv.f, new_sleep.c
 

  1. Compile el programa brecv. Ejecute el programa con dos nodos. El programa indicará el tiempo empleado por la tarea 0 en el blocking send.
  2. Edite brecv y reemplace el blocking receive con una llamada a MPI_Wait. Coloque un non-blocking receive antes de sleep. Compare el tiempo obtenido con el anterior.

Bibliografía

Tutorial on MPI: The Message-Passing Interface por William Gropp contiene láminas para una presentación y también está disponible como Postscript for Tutorial on MPI: The Message-Passing Interface
Example HR

Netscape Now   This page was created with Netscape Navigator Gold.


Última actualización: Septiembre 1999


 Regreso a la página personal de M.B. Ibáñez
e-mail: ibanez@ldc.usb.ve

Copyright © Netscape Communications