HERRAMIENTAS SOFTWARE PARA SISTEMAS DISTRIBUIDOS José Luis Pastrana Brincones (pastrana@lcc.uma.es) Departamento de Lenguajes y Ciencias de la Computación de la Universidad de Málaga Introducción. El hombre, cuando se plantea la resolución de un problema, por naturaleza obtiene una solución secuencial del mismo, es decir, nuestro cerebro trata de encontrar un método o algoritmo que siguiendo una serie de pasos nos conduzca a la solución del problema. Cuando nos planteamos el resolver un problema de manera distribuida, carecemos de esa estructura innata, por lo que debemos disponer de un modelo de programación, es decir, de un mecanismo para poder expresar la estructura lógica de un programa que resuelva un determinado problema. Un modelo de programación para sistemas distribuidos debe de tener los siguientes componentes: un modelo de los datos, un modelo de los procesos, un modelo de comunicación, un modelo de sincronización y un modelo de entrada/salida. Dicho modelo se verá influenciado por la complejidad del programa (costes de desarrollo y legibilidad del mismo tanto para su análisis como su mantenimiento) y por el rendimiento del mismo (influenciado tanto por el modelo como por su implementación). Los sistemas paralelos han originado gran cantidad de modelos de programación, lo que conlleva a dificultades o riesgos a la hora de elegir el más adecuado a nuestro problema, ya que frecuentemente, dichos modelos toman solo estructuras simplificadas con la finalidad de ser generales a costa de la claridad y/o de la eficiencia. El Modelo de Datos. A la hora de definir el modelo de datos para un modelo de programación paralela, debemos tener en cuenta los siguientes aspectos: • Espacio de Nombres. ◊ Nombres simbólicos o numéricos. ◊ Datos lineales o estructurados. • Tipos del Modelo. ◊ Definir o no nuevos tipos para la programación paralela. • Tiempo de vida de las variables. ◊ Estáticas ◊ Dinámicas. • Acceso ◊ Local (privado). ◊ Compartido (implica gestionar su coherencia). Modelo de Procesos. El modelo de procesos debe especificar el flujo de ejecución, es decir, la secuencia de operaciones que pueden ser ejecutadas por cada uno de los procesadores. Debiendo definir qué entendemos por proceso, el tiempo de vida del mismo y la forma de nombrarlo. • Procesos ◊ Programa en ejecución. ◊ Entidad activa capaz de realizar cómputo. ◊ Flujo de Control + Contexto Asociado ∗ Lightweight (Hebras). ∗ Heavyweight (Tareas o Procesos). • Tiempo de Vida. ◊ Estático / Dinámico. • Identificación de Procesos (nombre). ◊ Usado para el control de los procesos. ◊ Usado para el particionamiento del cómputo. ◊ Usado para la comunicación entre procesos. Combinado los dos modelos anteriores podemos obtener las siguientes estructuras básicas de programación paralela. • Memoria compartida. Varios procesos comparten un espacio de memoria común. • Memoria Distribuida (SPMD). Un proceso utiliza varios espacios de memoria distribuidos. • Memoria Distribuida (MPMD). Varios procesos utilizan un espacio de memoria distribuido. • Memoria Distribuida con múltiples hebras. Varias hebras (threads) de un mismo proceso utilizan un espacio de memoria distribuido. • Memoria compartida con datos privados. Varios procesos utilizan un espacio de memoria compartido junto con un espacio de memoria local o privado. Modelo de Comunicación A la hora de comunicar los procesos tenemos varias aproximaciones y una serie de patrones atener en cuenta en las mismas: • Aproximaciones Básicas ◊ Memoria Compartida. ◊ Memoria Distribuida. • Patrones. ◊ Exclusión mutua. ◊ Comunicación punto a punto. ◊ Reducciones. ◊ Difusión (Broadcast y Multicast). • Características de los Modelos de Comunicación Basados en Memoria Compartida. ◊ Problemas: ∗ Coherencia (memoria virtual, cache, etc. ) ∗ Consistencia de los datos. ∗ Acceso asociativo o directo. ◊ Necesitamos un mecanismo que combine el espacio de direcciones locales y globales. ◊ Existen interfaces soportados directamente por la arquitectura. • Características de los Modelos de Comunicación Basados en Paso de Mensajes. (Memoria Distribuida.) ◊ Se requiere cooperación entre los flujos de control. ◊ Frecuente buffering de la información antes de la comunicación. ∗ Para mejorar la eficiencia de la transmisión. ∗ Para soportar el empaquetado/desempaquetado de los datos. ◊ Pobre soporte hardware. ◊ Diferentes aspectos semánticos ◊ Códigos portables. ◊ Patrones de comunicación ∗ Punto a punto ( 1 a 1 ). ∗ Difusión (Broadcast , 1 a n ). ∗ Receptor único (n a 1). ∗ Cualquier proceso con privilegio puede recibir (n a n ). ◊ Interfaces de Comunicación. ∗ Asíncrono. Los procesos no deben establecer una cita o un método de notificación y aceptación del mensaje. El proceso que desee enviar un mensaje lo hace sin que necesite saber si hay alguien dispuesto a recibir dicho mensaje. Implica buffering. ∗ Síncrono. El proceso que envía un mensaje debe esperar a que el receptor acepte el mensaje para proseguir su tarea. ◊ Flexibilidad ∗ Selección de mensajes por su tipo ( No FIFO). ∗ El tipo del mensaje constituye una información adicional. ∗ Búsqueda del receptor requerido. Modelos de sincronización En los sistemas de memoria compartida debemos establecer primitivas de sincronización entre los procesos de forma explícita, mientras que en los sistemas basados en paso de mensajes, dicha sincronización viene implícita en la comunicación. • Implícita en la comunicación. (Paso de Mensajes). ◊ Recepción del mensaje ◊ Envío bloqueante: cita (rendez-vous) • Explícita. (Memoria Compartida). ◊ Exclusión mutua (semáforos). ◊ Notificación 1 a 1. ◊ Notificación 1 a varios. ◊ Barreras El Modelo de Entrada/Salida. Mientras en los modelos de memoria compartida la entrada/salida esta bastante bien definida, ya que la entrada/salida estándar o los ficheros que se deseen utilizar corresponden a una misma máquina, en los modelos de memoria distribuida, que por lo general consisten en una serie de máquinas conectadas en una red, se plantea una serie de problemas tales como definir la entrada/salida estándar o la localización de ficheros. Para la localización de ficheros de entrada el problema no tiene excesiva complicación, ya que se soluciona fácilmente replicando dichos ficheros en las diferentes máquinas, pero a la hora de la entrada por consola o a la hora de salida de datos por pantalla/fichero la solución no es tan trivial. Se suelen utilizar varios sistemas. Una posible solución para todos los problemas es tener un nodo distinguido en la red que sea el que realiza todas las tareas de entrada/salida y se encarga de distribuir y recibir los datos de/a todos los demás nodos, esta seria la solución más simple, pero conllevaría una sobrecarga en el número de comunicaciones entre los diferentes nodos, así como la introducción de un gran número de puntos de sincronización. La segunda opción, y normalmente más usada, consiste en realizar todas las posibles entradas mediante un fichero que este replicado en los diferentes nodos y que cada nodo realice su salida a un fichero local (en su propio nodo), con posterioridad a la ejecución (offline) se tiene un programa de mezcla (merge) que combina todos los ficheros de salida parciales en uno solo que refleja la salida real del sistema. La realización de este programa de mezcla no es siempre posible ni sencillo, así que será tarea del diseñador del sistema distribuido el decidir la técnica a utilizar en función de sus requerimientos temporales de ejecución del sistema. Algunas herramientas software para sistemas distribuidos (como PVM, por ejemplo) implementan esta última opción para resolver el problema de la salida estándar en los procesos “hijos” (todos los procesos que son expandidos por uno inicial) , creando un fichero de log en el que escribe dichas salidas. Memoria Compartida VS Memoria Distribuida. El establecer cuál de los dos mecanismos básicos de comunicación para un programa paralelo o un sistema distribuido se torna en un problema de difícil decisión en el que los diferentes autores que escriben sobre el tema no llegan a ponerse de acuerdo, por lo que realizaremos una valoración de ambos en función de dos parámetros que pueden ser decisivos a la hora de elegir el mecanismo a utilizar en nuestro sistema: la granularidad (tamaño de los procesos) y la cantidad de comunicación. A nivel general, podemos decir que los sistemas basados en memoria compartida tienen la ventaja de que las primitivas de sincronización están soportadas por el hardware, sin embargo, los sistemas basados en paso de mensajes expresan de una manera más legible las diferentes tareas realizadas por el sistema , así como la interrelación entre las mismas. En el desarrollo de sistemas en que la granularidad de los procesos sea fina (unas pocas líneas de código) y con una gran cantidad de datos, los sistemas basados en memoria compartida tienden a ser más eficientes y permiten un desarrollo incremental, ya que podemos desarrollar el programa de forma secuencial y luego describir los diferentes procesos. Un ejemplo claro de esto podría ser el empleo de bucles paralelos (DO ACROSS) en algoritmos de cálculo matricial. Primero podemos realizar el algoritmo secuencial (DO) y luego ejecutarlo con una sentencia de paralelización del bucle (DO ACROSS). Sin embargo, en el desarrollo de sistemas que usen procesos de granularidad gruesa (procesos que son procedimientos, funciones o incluso programas completos), se incrementa la legibilidad, ya que cada proceso constituye una tarea concreta, y si las tareas no están fuertemente acopladas (no dependen excesivamente unas de otras) el intercambio de información entre ellas no será ningún impedimento para obtener una buena eficiencia. Debemos añadir a nivel general, que los sistemas distribuidos son de coste más bajo y más fácilmente escalables, ya que un sistemas distribuido puede estar formado por una serie de estaciones de trabajo conectadas en red ,por ejemplo, cuyo precio es muy inferior al de un multiprocesador de memoria compartida y incrementar el número de nodos consiste sólo en enganchar una nueva estación a la red, mientras que en un multiprocesador el número de procesadores estará limitado por el espacio físico en la placa y el incremento de los mismo suele ser de mayor coste. A ésto debemos añadir que las redes de comunicación han experimentado un gran incremento en su velocidad y fiabilidad, así como el software de comunicación a través de las mismas. PVM. Características Generales. • Está basada en la idea de una máquina virtual paralela. • Disponible gratuitamente por Oak Ridge Nat. Lab. • Pensada para una red de estaciones de trabajo (aunque exiten versiones para multiprocesadores y para PC’s, tanto para Linux, OpenServer, etc , como para Windows). • Permite combinar máquinas gran variedad de máquinas heterogéneas. Modelo de Programación. • Tareas con hebra simple ( una sóla hebra por tarea). • Nombrado de tareas: ◊ Identificador de tarea numérico, único y global que se usa para la comunicación y control de procesos. ◊ Posibilidad de definición de grupos con un nombre simbólico local y dinámico. Un proceso puede pertenecer a más de un grupo. • Creación dinámica de tareas. • Admite excepciones de sistema basadas en señales UNIX. Modelo de Comunicación. • Semántica de mensajes. • No tipado. • uso de buffer. ◊ buffers implícitos de envío y recepción. ◊ funciones de manejo de buffers. ◊ funciones de empaquetado/desempaquetado. ◊ codificación XDR (para máquinas heterogéneas) o directa (para máquinas homogéneas). • Mensajes etiquetados. • Recepción bloqueante y no bloqueante. • Envíos no bloqueantes (asíncrono). • Interface síncrono. • Multicast a un grupo de tareas o Broadcast. • Soporta enrutado directo. Modelo de Sincronización. • Semántica de sincronización basada en mensajes. • Posibilidad del uso de barreras. Modelo de Entrada/Salida. • Salida estándar de consola y de errores redireccionada al archivo /tmp/pvml.<uid> de la máquina inicial. Implementación. • Estructura General. ◊ Librerías + Demonios. ◊ pvm: Consola de comandos de control de procesos y sistema. ◊ Comunicación basada en sockets o sistema nativo de la máquina (por ejemplo memeoria compartida en multiprocesadores). ◊ Archivo de configuración para la máquina virtual (hosts que la componen). • Configuración. ◊ Utiliza los comandos rsh, rexec para lanzar los demonios y las tareas. ◊ Permite añadir hosts en tiempo de ejecución. • Identificador de Tareas. El identificador de tareas genérico se compone de dos campos, el más significativo contiene un indicador del hosts y el menos significativo el identificador del proceso. En el caso de trabajar con máquinas de memoria compartida, este segundo campo se divide en dos, uno para identificar el procesador y otro el proceso). • Creación de procesos. El demonio local es el encargado de lanzar el proceso en la máquina. MPI. Características Generales. • Se ha realizado un gran esfuerzo de estandarización de paso de mensajes. ◊ Auna esfuerzos y criterios de otros desarrollos de modelos de programación con el fin de desarrollar un estandard. ◊ Semática variada: Extenso interfaz. ◊ Modelo tipado. • Fuerte apoyo industrial. Modelo de Procesos. • MIMD. • Procesos estáticos (no se permite la creación dinámica de procesos). • Interfaz seguro para hebras. • Grupos. Permite la definición de grupos de procesos. • Topología. • No maneja señales y Entrada/Salida. Modelo de Comunicación. • Semántica de mensajes. • Mensajes tipados. • Comunicación soportada por librerías. • Interfaz síncrono y asíncrono. • Bufferización en los mensajes. • Recceción ordenada de mensajes. • Manejo de buffers: el usuario provee los buffers internos para MPI. • Comunicación colectiva: Broadcast, Gather, Scather, Gather to All. • Operaciones de reducción: Predefinidas y definidas por el usuario. Modelo de Sincronización. • Semántica de sincronización por paso de mensajes. • Barreras. PARMACS. Características Generales. • Es comercial. ◊ La versión 5.0 está basada en macros. ◊ La versión 6.0 está basada en llamadas a funciones. • Está diseñado para paso de mensajes en arquitecturas paralelas. Modelo de Procesos. • Programas parar Host y nodos. • Funcionalidad de control global de procesos para nodos incocados desde un hosts. • Primitivas de inicialización. • Descripcción de la topología ◊ Mapeo de la topología física del sistema. ◊ Definir un espacio de nodos. ◊ Optimización de comunicaciones. ◊ Influencia semántica de las funciones(sliced-barrier). • Procesos de hebra simple. • Espacio de nombre numérico y lineal. Modelo de Comunicación. • Comunicación directa. • Mensajes etiquetados. • Semántica de mensajes. • Comunicación síncrona y ansíncrona (permite ambas). • Selección flexible de mensajes recibidos. • No incorpora Broadcast. • Soporta manejo de buffers automático. • Formato implícito para soporte de sistemas heterogéneos. Modelo de sincronización. • Semántica de sincronización de mensajes. • Barreras