MPJ-Express, modelos teóricos de control de la concurrencia con paso de mensjaes.
Paso de mensajes
Todos los modelos teóricos de control de la concurrencia analizados se basan en la existencia de memoria compartida, a través de la cuál las hebras se comunican a efectos de sincronizar su ejecución.
En sistemas donde esta memoria no existe (sistemas distribuidos, clusters de procesadores), ese conjunto de técnicas no es aplicable. Por lo que necesitamos un nuevo modelo, que estructure la comunicación y sincronización entre hebras mediante el envío de mensajes (a través de algún medio de comunicación).
Ahora las hebras (en general, las tareas) se comunican mediante operaciones de envío y receptión de información de naturaleza explícita.
Arquitectura básica
Se utiliza el concepto de canal como medio común a las tareas que se comunican, el cual es una abstracción software que puede modelar a diferentes realidades físicas, como una red de comunicaciones, internet, o incluso un espacio de memoria común, si este existe y así se decide.
Ahora las tareas envían información al canal (mediante una operación de envío) o la reciben desde el canal (mediante una operación de recepción).
Ventajas
Es aplicable en prácticamente cualquier arquitectura de computadores:
- En sistemas distribuidos
- En sistemas paralelos con/sin memoria común
- En clusters de procesadores
No existe el problema del acceso a datos compartidos y toda la problemática que el mismo conlleva.
Identificación de procesos
Es necesario determinar cómo se identifican entre sí los procesos emisores y receptores de una aplicación:
-
Denominación directa
- Utilizan directamente los id de los procesos, debiendo asignarse previamente a la ejecución del programa y manteniéndose posteriormente. Si se cambian, hay que recompilar el código de la aplicación
-
Denominación indirecta
- Utiliza un objeto intermedio denominado buzón, los procesos designan al mismo buzón como destino u origen de los mensjaes que se intercambian
Ejemplos:
// direccionamiento directo
// Proceso P0
int dato;
produce(dato);
send(&dato, P1);
// Proceso P1
int x;
receive(&x, P0);
consume(x);
// direccionamiento indirecto
Channel of Integer Buzon;
//Proceso P0
int dato;
produce(dato);
send(&dato, Buzon);
// Proceso P1
int x;
receive(&x, Buzon);
consume(x);
Semántica de las operaciones
send
y receive
Puede variar, dependerá de la seguridad y el modo de comunicación.
Propiedad de seguridad: una operación send
es segura cuando existen garantías de que el valor recibido por el proceso destino es el que tiene los datos justo antes de la llamada en el proceso origen.
Sincronización
-
Operaciones síncronas, el intercambio de un mensaje es una operación atómica que exige la participación simultánea del emisor y receptor (rendezvouz)
-
Operaciones asíncronas, el emisor envía el mensaje sin bloquearse, y el emisor lo puede recoger más tarde; requiere de la existencia de un buzón intermedio.
Operaciones síncronas
La comunicación se lleva a cabo mediante un enlace directo entre los procesos implicados.
Las operaciones son bloqueantes, un proceso A no envía si el proceso B de destino no está preparado para recibir. Mientras, A espera.
Un proceso B espera bloqueado para recibir a que haya un proceso A que efectúe un envío.
Por tanto, antes de que los datos se envíen de forma física, ambos procesos han de estar preparados para participar en el intercambio. Debe producirse una cita o rendezvous.
Esto implica:
- Sincronización entre emisor y receptor
- El emisor puede realizar aserciones acerca del estado del receptor en el punto de sincronización
Operaciones asíncronas
receive posee la misma semántica que el paso de mensajes síncrono. Extraerá los mensajes del buzón intermedio, pero bloqueará al receptor si dicho buzón está vacío.
send posee una semántica diferente, ya que ahora no tiene carácter bloqueante.
El proceso emisor envía, send, su mensaje al buzón, y continúa la ejecución normal. Eventualmente, el envío podría llegar a tener carácter bloqueante si el buzón intermedio llegara a llenarse.
Bibliotecas de paso de mensajes
-
MPI (C/C++, Fortran, etc.) y sus versiones para Java (MPJ-Express) son muy utilizados para programación paralela con paso de mensajes en arquitecturas multicore de memoria común y clusters de procesadores.
-
JCSP es una implementación más abstracta y más cercana al concepto de canal expuesto.
La programación en Java con sockets y con el framework RMI ofrece soporte a la programación distribuida basada en el paso de mensajes con un mayor nivel de abstracción.
MPI, message passing interface
Uno de los frameworks más utilizados para programación paralela y distribuida mediante paso de mensajes entre procesos.
Teóricamente soporta el nivel MIMD de la taxonomía de Flynn. Sin embargo, en la práctica, la mayoría de aplicaciones escritas con él utilizan el modelo SPMD, donde todos los procesos ejecutan el mismo programa sobre datos diferentes.
Obviamente, esos programas no necesariamente han de ejecutar la misma instrucción al mismo tiempo.
MPJ-Express, es una implementación de MPI para Java (sobre multicore y clusters)
Funciones
Proporciona funciones de comunicación punto a punto para dos procesos, y funciones colectivas que involucran a un grupo de procesos.
Los procesos pueden agruparse mediante el concepto de comunicador, lo que permite determinar el ámbito de las funciones colectivas y el diseño modular.
MPJ-Expres incluye funciones para realizar operaciones:
- Básicas
- Comunicación punto a punto
- Comunicaciones colectivas
- Control de la topología del espacio de procesos
- Gestión e interrogatorio del entorno
Funciones básicas
MPI.Init()
para iniciar la ejecución paralelaMPI.COMM_WORLD.Size()
para determinar el número de procesos en ejecución paralelaMPI.COMM_WORLD.Rank()
para que cada proceso obtenga su identificador dentro de la colección de procesos que forman la aplicaciónMPI.Finalize()
para terminar la ejecución del programa
Comunicadores de MPJ-Express
Un comunicador es un universo de comunicación de MPJ-Express que define a un grupo de procesos que se pueden comunicar entre sí. Todas las funciones de comunicación de MPJ-Express necesitan involucrar a un comunicador.
Todo mensaje de MPJ-Express debe involucrar a un comunicador. El comunicador especificado en las llamadas a operación de envío y recepción debe concordar para que la comunicación sea posible.
Pueden existir múltiples comunicadores y un proceso puede formar parte de varios
Dentro de los comunicadores los procesos se numeran (y se identifican) consecutivamente (empezando por 0). Este es el rank
del proceso. Un proceso con varios comunicadores puede tener diferentes rank
en cada uno.
MPJ-Express proporciona un comunicador básico por defecto, MPI.COMM_WORLD
, que incluye a todos los procesos.
Comunicaciones punto a punto
Hay dos procesos emisor y receptor, deben programarse explícitamente operaciones de envío (en el emisor) y de recepción (en el receptor).
Todo mensaje de MPJ-Express debe involuclar un comunicador, con su id.
Las operaciones más simples del API para enviar y recibir son:
void Send(bufer, offset, datatype, destination, tag)
Status Recv(bufer, offset, datatype, source, tag)
También existe comunicación uno a muchos
Objeto Status
El resultado de una operación de recepción es un objeto de clase Status
, el cual permite obtener información del mensaje recibido y de su tamaño. Esto se produce cuando los procesos que envían y reciben sincronizan en el mensaje.
Operaciones bloqueantes
Las operaciones Send
y Recv
descritas son bloqueantes, el proceso que las usa permanece bloqueado hasya que la operación que invocan está completada. Esto se produce cuando los procesos que envían y reciben sincronizan entre sí el mensaje.
Punto a punto síncronas
Las operaciones de envío y recepción realizan un envío sin búfer, bloqueante en los dos extremos que se comunican.
Ahora las operaciones son las siguientes:
void SSend(bufer, offset, datatype, destination, tag)
Status Recv(bufer, offset, datatype, source, tag)
La operación de envío SSend
finaliza sólo cuando la operación Recv
correspondiente sea invocada por otro proceso y el receptor haya comenzado a recibir el mensaje.
Cuando SSend
devuelve el control, la zona de memoria que alberga el dato puede ser reutilizada y el receptor habrá alcanzado el punto de su ejecución que corresponde a la llamada de la función de recepción.
Si la operación de recepción es bloqueante (por ejemplo, Recv
) la semántica del paso de mensaje es síncrona (existe cita entre emisor y receptor)
Operaciones de comunicación colectiva
Afectan a todos los procesos de un comunicador concreto. Todos los procesos del comunicador las deben llamar con parámetro iguales. Están definidas en la clase Intracomm