Tema 4: SISTEMAS BASADOS EN PASO DE MENSAJES

Anuncio
Tema 4. Sistemas basados en paso
de mensajes
Programación Concurrente
Depto. de Lenguajes y Sistemas Informáticos
Universidad de Granada
Contenidos
1. Introducción
2. Sentencias básicas de paso de mensajes
2.1. Sentencias bloqueantes
2.2. Sentencias no bloqueantes
3. Espera selectiva
4. La Interfaz de Paso de Mensajes (MPI)
4.1. Modelo de Programación
4.2. Funciones básicas
4.3. Comunicación no bloqueante
1. Introducción
•
Multicomputador-programación distribuida / Multiprocesador progr. con
memoria compartida
–
–
Extensiones de la máquina de Von-Neuman
Multiprocesador ⇒ Memoria Compartida
•
•
•
–
•
Más fácil programación
Mayor Coste: Acceso a Memoria Común = cuello de botella
Escalabilidad Hardware limitada
Solución: Multicomputador ⇒ Distribución de los datos/recursos
Necesidad de una notación de programación distribuida
–
Lenguajes tradicionales (memoria común)
•
•
–
Extra añadido: Envío / Recepción → Afectan al entorno externo
•
•
–
Asignación: Cambio del estado interno de la máquina.
Estructuración: Secuencia, repetición, alternación, procedimientos, etc.
Tan importante como la asignación
Permiten comunicar procesos que se ejecutan en paralelo
Paso de mensajes:
•
•
Abstracción: Oculta Hardware (red de interconexión).
Se puede implementar eficientemente en todas las arquitecturas.
1. Introducción
Programación con paso de mensajes
•
•
Asume espacio de direcciones particionado
Vista lógica Arquitectura
–
–
•
Estructura de un Programa de Paso de Mensajes
–
–
•
Asíncrona: Todos los procesos se ejecutan asíncronamente.
Débilmente síncrona: Los procesos se sincronizan para las interacciones.
Entre interacciones, trabajan asíncronamente.
Enfoque general: Ejecución programa diferente sobre cada proceso.
–
•
P procesos, cada uno con su espacio de direcciones propio
Interacciones requieren cooperación entre 2 procesos: propietario datos
debe intervenir aunque no conexión lógica con evento tratado en receptor.
Difícil en la práctica.
Enfoque común: SPMD (Single Program Multiple Data)
–
Código que ejecutan diferentes procesos es idéntico excepto para pequeño
número de procesos.
2. Sentencias básicas de
paso de mensajes
Send (void *sendbuf, int nelems, int dest)
Receive(void *recvbuf, int nelems, int source)
•
Ejemplo simple: Semántica requiere que valor recibido sea 100 en lugar
de 0.
P0
a=100;
send(&a,1,1);
a=0;
–
•
P1
receive(&a,1,0);
printf("%d\n",a);
Necesario asegurar semántica, aunque existen casos en que no es deseable.
Soporte hardware para envío/recepción: muy común
–
–
–
DMA (Acceso Directo a Memoria): Copiar datos entre posiciones de memoria.
Interfaces de red: Transferencia de mensajes sin intervención de la CPU.
Si “send” programa hardware de comunicación y devuelve control antes de completar
• P1 recibe un 0 en lugar de 100.
2.1. Sentencias Bloqueantes
•
Solución bloqueante: send retorna cuando se garantice semántica
(seguridad).
– No significa que receptor haya recibido el dato
– 2 mecanismos: no buferizado /buferizado
2.1.1. Send-Receive bloqueante no buferizado
•
•
Send no retorna hasta receive correspondiente encontrado en
receptor
Exige cita entre emisor y receptor. No hay búfer.
1. Emisor envía petición comunicación a receptor y espera confirmación.
2. Receptor sólo responde a petición cuando encuentra receive.
3. Tras recibir confirmación, Emisor inicia transferencia.
2.1. Sentencias Bloqueantes
2.1.1. Send-R eceive bloqueante no buferizado
Inconvenientes:
•
Sobrecarga por espera ociosa:
–
Adecuado sólo cuando send/receive se inician aprox. mismo tiempo.
Emisor
send
Receptor
Emisor
Receptor
Petición
Listo
datos
•
Emisor
Receptor
receive
receive
send
Petición
Listo
receive
send
datos
Petición
Listo
datos
Interbloqueos: Necesario alternar en intercambios
–
Código engorroso de escribir y difícil de depurar.
P0
send(&a,1,1);
receive(&b,1,1);
P1
send(&a,1,0);
receive(&b,1,0);
2.1. Sentencias Bloqueantes
2.1.2. Send-R eceive bloqueante buferizado
•
Emisor/Receptor tienen búfer preasignado para comunicación.
–
–
Emisor copia datos a búfer y continúa tras copia (es seguro).
Cuando receptor encuentra “receive”, comprueba si el mensaje está disponible en el búfer de
recepción y copia datos en dirección destino.
a) Con hardware de comunicación: Transferencia se inicia tras copia a búfer.
b) Sin hardware especializado: sólo se buferiza un lado ---> menor sobrecarga
• Emisor interrumpe receptor y ambos procesos intervienen en transferencia.
• Receptor encuentra “receive” y mensaje es copiado al búfer de recepción.
• También posible al revés (receptor interrumpe emisor).
a)
Emisor
Receptor
b)
Emisor
Receptor
send
send
datos
datos
receive
Copia en búfer
de recepción
receive
2.1. Sentencias Bloqueantes
2.1.2. Send-R eceive bloqueante buferizado
•
•
•
Alivia sobrecargas de espera ociosa a costa de gestión de búfer.
Sólo menos ventajosas en programas altamente síncronos o cuando la
capacidad del búfer sea un asunto crítico.
Impacto de búfer finito: Escribir programas con requisitos de búfer acotados
–
–
P1 más lento que P0 ⇒ P0 podría continuar siempre que hubiese búfer.
Búfer agotado ⇒ P0 se bloquearía.
P0
for (i=0;i<1000;i++)
{produce(&a);
send(&a,1,1);}
•
P1
for (i=0;i<1000;i++)
{ receive(&a,1,0);
consume (&a);}
Interbloqueo con paso buferizado: llamadas a receive siguen siendo
bloqueantes.
P0
receive(&b,1,1);
send(&a,1,1);
P1
receive(&b,1,0);
send(&a,1,0);
2.2. Sentencias no bloqueantes
•
Protocolos bloqueantes: Garantizan semántica
–
–
•
sobrecarga de espera ociosa (no buferizado)
sobrecarga de gestión de búfer (buferizado)
Posibilidad: Requerir programador asegure semántica y usar
operaciones send/receive con baja sobrecarga.
–
–
–
Las operaciones devuelven el control antes de que sea seguro modificar datos.
Responsabilidad usuario: asegurar que no se alteran los datos.
Sentencias de chequeo de estado: indican si la semántica podría violarse.
•
•
•
Iniciada la operación, el usuario puede realizar cualquier cómputo que no
dependa de la finalización de la operación.
Cuando necesario se chequea el fin de la operación.
También existen dos posibilidades:
–
–
Buferizado
No buferizado
2.2. Sentencias no bloqueantes
2.2.1. Send-R eceive no bloqueante no buferizado
•
Proceso que desea enviar informa de un mensaje pendiente y continúa.
– El programa puede hacer mientras otro trabajo.
– Cuando el “receive” es confirmado, la comunicación se inicia.
– Operación de chequeo indica si es seguro tocar los datos.
•
Mejora: Tiempo de espera ociosa se puede emplear en computación
– Coste: reestructuración programa.
– Con hardware especializado: sobrecarga podría ser enteramente enmascarada
aunque los datos a recibir son inseguros hasta finalizar transferencia.
Emisor
a) Sin soporte
Hardware
send
Inseguro actualizar
datos a enviar
Emisor
Receptor
b) Con soporte
Hardware
send
Petición
Listo
datos
receive
Inseguro actualizar
datos a enviar
Receptor
Petición
Listo
datos
receive
Inseguro actualizar
datos a recibir
2.2. Sentencias no bloqueantes
2.2.2. Send-R eceive no bloqueante buferizado
•
Emisor inicia una operación de DMA y retorna inmediatamente.
–
Los datos se vuelven seguros en el momento en que DMA
completado.
•
En el receptor, “receive” inicia la transferencia desde el búfer
del emisor a la dirección destino en el receptor.
•
Efecto: reducir el tiempo durante el cual los datos son
inseguros.
•
MPI implementa tanto operaciones bloqueantes como no
bloqueantes.
–
–
Operaciones bloqueantes facilitan una programación más fácil y
segura.
Operaciones no bloqueantes permiten optimizar el rendimiento al
enmascarar sobrecargas de comunicación.
3. Espera Selectiva
•
Los modelos basados en paso de mensajes imponen ciertas
restricciones
–
•
No basta con send y receive para modelar la semántica deseada.
Productor Consumidor con búfer de tamaño fijo
–
–
Se asumen operaciones bloqueantes sin búfer
Problema: Acoplamiento forzado entre los procesos
PROC Productor
{
while (true){
....
Produce (&dato)
send (&dato,1,Consumidor)
....}
}
PROC Consumidor
{
while (true){
....
receive (&dato,1,Productor)
Consume (dato)
....}
}
3. Espera Selectiva
•
Mejora: Gestión intercambio mediante proceso Buffer
– Productor puede continuar después envío
– Problema: El búfer sólo puede esperar mensajes de un único emisor en
cada instante.
•
Aspecto común en aplicaciones cliente-servidor
– No se conoce a priori el cliente que hace la petición en cada instante
– Servidor debe estar preparado para recibir sin importar orden
PROC Productor
{
while (true){
....
Produce (&dato)
send (&dato,1,Buffer)
....}
}
PROC Buffer
{
while (true){
....
receive (&dato,1,Productor)
receive (&señal,1,Consumidor)
send (&dato,1,Consumidor)
....}
}
PROC Consumidor
{
while (true){
....
send (&señal,1,Buffer)
receive (&dato,1,Buffer)
Consume (dato)
....}
}
3. Espera Selectiva
•
Solución: Espera selectiva con varias alternativas guardadas
–
–
Se evalúan todas las guardas (condiciones)+alternativas
Elección aleatoria entre las que:
•
–
–
–
–
Se ejecutan las sentencias de la alternativa seleccionada
No emparejamiento ⇒ Bloqueo hasta evento
Existe select con prioridad
SELECT {
Evaluación guardas
condición1, receive (&mensaje1,count1, fuente1);
•
•
–
Emparejen con envío y cuyas guardas se evaluaron como ciertas
Una vez al comienzo sentencia
Sólo se reevaluarán si se
vuelve a ejecutar el select
Son opcionales:
•
•
la guarda y
la sentencia de recepción
<sentencias>;
or
condición2, receive (&mensaje2,count2, fuente2);
<sentencias>;
or
…..
or
condiciónN, receive (&mensajeN, countN, fuenteN);
<sentencias>;}
3. Espera Selectiva
•
Productor consumidor con buffer de tamaño fijo
–
–
–
Buffer no conoce a priori orden de peticiones (Inserción/Extracción)
Guardas controlan condiciones de sincronización (seguridad)
¿Cuándo termina buffer?
•
Sentencia select con temporizador (timeout).
PROC Productor {
for(i=0;i<10;i++)
{Produce (&dato)
send (&dato,1,Buffer);}
}
PROC Buffer
const tam=10;
int buf[tam], cont=0, in=0, out=0;
{while (true){
SELECT {
cont<=tam, receive (&dato,1, Productor);
buf[in]=dato; in=(in%tam)+1;cont++;
or
cont!=0, send(&(buf[out]),1,Consumidor);;
out=(out%tam)+1; cont--;}
}
PROC Consumidor
{
for(i=0;i<10;i++)
receive (&dato,1,Buffer)
Consume (dato);}
}
Descargar