Subsecciones

6.1 The openMosix internals (Moshe Bar)

Aspectos generales de openMosix

Un cluster openMosix es del tipo SSI. Se ha argumentado mucho sobre si estas arquitecturas pueden considerarse un cluster como tal. Los primeros clusters SSI fueron el IBM SySPlex y un cluster de DEC. En el cluster DEC se podía acceder con telnet a la dirección del cluster y trabajar desde allí hasta que decidiéramos terminar la conexión. El usuario nunca tenía consciencia sobre en cual de los nodos se encontraba y cualquier programa que se lanzara se ejecutaba en el nodo que mejor pudiera servir las necesidades del proceso.

Bien, openMosix es exactamente lo mismo. Sólo que funciona sobre nuestro sistema operativo favorito: Linux!

openMosix es una extensión del kernel. Antes de instalar openMosix tendremos que lanzar el script de instalación que hará efectivos los cambios necesarios al kernel de linux -por lo tanto deberemos disponer de las fuentes del kernel en nuestro disco-. Los cambios se traducen entorno a un 3% del código total del núcleo, lo que realmente no es muy significativo.

Cuando habremos recompilado el nuevo kernel y tras arrancarlo, dispondremos de un nuevo nodo openMosix. Haciendo réplicas de este proceso en las máquinas que tengamos en nuestra red llegaremos a crear el cluster.

Hay un fichero de configuración en /etc/openmosix.map que debe ser configurado para dejar ver en el nodo local -el poseedor del fichero- los demás nodos. Cada nodo envía su estado de carga actual a una lista aleatoria de otros nodos, para hacerlo conocer. La mejor característica de openMosix es que podemos ejecutar un programa y el mismo cluster decide dónde debe ejecutarse.

openMosix nos brinda una nueva dimensión de la escalabilidad de un cluster bajo linux. Permite la construcción de arquitecturas de alto rendimiento, donde la escalabilidad nunca se convierte en un cuello de botella para el rendimiento general del cluster. Otra ventaja de los sistemas openMosix es la respuesta en condiciones de alta impredicibilidad producida por distintos usuarios y/o situaciones.

Entre las características más relevantes se encuentra su política de distribución adaptativa y la simetría y flexibilidad de su configuración. El efecto combinado de estas propiedades implica que los usuarios no tengan que saber el estado actual de los distintos nodos, ni tan siquiera su número. Las aplicaciones paralelas pueden ser ejecutadas permitiendo el asignamiento del lugar de ejecución de los procesos a openMosix. Como puede darse en sistemas SMP.

No obstante hay áreas donde openMosix no genera grandes beneficios. Para aplicaciones que usen memoria compartida (como servidores de web o de bases de datos) los procesos no podrán migrar y por tanto permanecerán en el nodo desde el cual se han invocado.

Detalles de openMosix

openMosix es una herramienta para kernels Unix, como Linux, consistente en unos algoritmos para adaptación de recursos compartidos. Permite múltiples nodos uniprocesadores -UPs- y/o SMPs que funcionen bajo la misma versión del kernel para cooperar conjuntamente. Los algoritmos de openMosix se han diseñado para responder a variaciones a tiempo real en el uso de los recursos de varios nodos. Esto es posible migrando procesos de un nodo a otro transparentemente, teniendo en cuenta la carga de cada uno de ellos y evitando errores debido al uso de memoria swap. El éxito es una mejora en el rendimiento total y la creación de un entorno multiusuario y de tiempo compartido para la ejecución de aplicaciones, tanto secuenciales como paralelas. El entorno de trabajo estándar de openMosix es un cluster donde se encuentran disponibles todos y cada uno de los recursos de cada nodo.

La implementación actual de openMosix se ha diseñado para configurar clusters con máquinas basadas en x86 conectadas en redes LAN estándar. Las posibles configuraciones abarcan desde pequeños clusters con redes de 10Mbps hasta entornos con servidores SMP y redes ATM, Gigabit LAN o Myrinet. La tecnología openMosix consiste en dos partes:

  1. un mecanismo de migración de procesos llamado Migración Preferente de Procesos (PPM),
  2. un conjunto de dos algoritmos para la compartición adaptativa de recursos,
  3. y un sistema para el acceso a ficheros de cualquier nodo del cluster.

Ambas partes están implementadas a nivel de kernel utilizando módulos, la interfaz del kernel permanece sin modificar. Todo ello permanece transparente a nivel de aplicación. Se profundiza sobre cada una de ellas en las próximas subsecciones.

La PPM puede migrar cualquier proceso, en cualquier instante de tiempo y a cualquier nodo disponible. Usualmente las migraciones estan basadas en información provinente de uno de los algoritmos de compartición de recursos, pero los usuarios pueden invalidar cualquier decisión automática y hacer las migraciones manualmente.

Una migración debe ser iniciada por el proceso o por una petición explícita de otro proceso del mismo usuario (o del super-usuario root). Las migraciones manuales de procesos pueden ser útiles para implementar una política particular o para testear diferentes algoritmos de planificación (scheduling). Cabe destacar que el super-usuario tiene privilegios adicionales sobre la PPM, como la definición de políticas generales o qué nodos podrán ser incluidos en el cluster y cuáles no.

Cada proceso tiene un único nodo de origen (UHN, unique home node) donde es creado. Normalmente éste es el nodo en el cual el usuario ha logado. El modelo SSI de openMosix es un modelo CC (cache coherent), en el cual cualquier proceso parece ejecutarse en su nodo local y donde todos los procesos de una sesión de usuario comparten el entorno de la ejecución del UHN. Los procesos que migran a otro nodo usarán los recursos de éste, siempre que sea posible, pero interaccionarán con el usuario a través del UHN. Por ejemplo, podemos suponer que un usuario invoca ciertos procesos, algunos de los cuales pasan a migrarse a nodos remotos. Si el usuario ejecuta a continuación el comando ps podrá ver el estado de todos sus procesos, incluyéndose los procesos migrados. Si alguno de los procesos migrados pide la hora actual a través de la primitiva gettimeofday() obtendrá la hora del UHN.

La política que implementa PPM es la principal herramienta para los algoritmos de gestión de los recursos. Mientras recursos como el uso de procesador o de memoria principal se encuentren bajo cierto umbral, los procesos serán confinados al UHN. Cuando los requerimientos de los recursos exceda de ciertos niveles, algunos procesos se migrarán a otros nodos para aprovechar las ventajas de los recursos remotos. La principal meta es maximizar la eficiencia de recursos a través de la red. La unidad de granularidad del trabajo de distribución en openMosix es el proceso6.1. Los usuarios pueden ejecutar aplicaciones paralelas inicializando múltiples procesos en un nodo, y luego permitiendo al sistema la asignación de dichos procesos a los mejores nodos disponibles. Si durante la ejecución de los procesos aparecen nuevos recursos usables, los algoritmos de gestión de recursos compartidos se encargarán de tenerlos en cuenta. Esta capacidad para asignar y reasignar procesos es particularmente importante para facilitar la ejecución y proporcionar un entorno multiusuario y de tiempo compartido eficiente.

openMosix no dispone de un control centralizado -o jerarquizado en maestros/esclavos-: cada nodo puede operar como un sistema autónomo, y establece independientemente sus propias decisiones. Este diseño permite la configuración dinámica, donde los nodos pueden añadirse o dejar el cluster con interrupciones mínimas. Adicionalmente permite una gran escalabilidad y asegura que el sistema permanezca funcionando correctamente en grandes o pequeñas configuraciones. Dicha escalabilidad se consigue incorporando aleatoriedad en los algoritmos de control del sistema, donde cada nodo basa sus decisiones en un conocimiento parcial sobre el estado de cada uno de los demás nodos. Por ejemplo, en el algoritmo probabilístico de difusión de información, cada nodo envía, a intervalos regulares, información sobre sus recursos disponibles a un conjunto de nodos elegidos aleatoriamente6.2. Al mismo tiempo, mantiene una pequeña ventana con la información llegada más reciente. Este esquema soporta escalabilidad, difusión de información uniforme y configuraciones dinánimcas.

Mecanismo de migración de procesos PPM

La mejor aportación de openMosix es un nuevo algoritmo para seleccionar en qué nodo debe ejecutarse un proceso ya iniciado. El modelo matemático para este algoritmo de planificación (scheduling) se debe al campo de la investigación económica. Determinar la localización óptima para un trabajo es un problema complicado. La complicación más importante es que los recursos disponibles en el cluster de computadoras Linux son heterogéneos. En efecto, el coste para memoria, procesadores, comunicación entre procesos son incomparables: no se miden con las mismas unidades. Los recursos de comunicación se miden en términos de ancho de banda, la memoria en términos de espacio libre y los procesadores en términos de ciclos por segundo.

openMosix implementa la migración de procesos completamente transparente al usuario, al nodo y al proceso. Tras su migración el proceso continúa interaccionando con el entorno de su localización. Para implementar PPM la migración de procesos se divide en dos áreas:

  1. remote: es el área de usuario y puede ser migrada.
  2. deputy: es el área de sistema, que es dependiente del UHN y que no puede migrar.
A continuación se detalla sobre cada una de ellas.



I.- REMOTE



Contiene el código del programa, el stack, los datos, los mapas de memoria y los registros de los procesos. Remote encapsula el proceso cuando está ejecutándose a nivel de usuario.



II.- DEPUTY



El área de sistema, llamada también parte delegada, contiene una descripción de los recursos a los que el proceso está ligado y un kernel-stack para la ejecución del código de sistema del proceso. Deputy encapsula el proceso cuando está ejecutándose en el kernel. Mantiene la dependencia de las partes del contexto del sistema de los procesos, por lo tanto debe mantenerse en el UHN. Mientras el proceso puede migrar -y varias veces- entre nodos diferentes, el deputy nunca lo hará. La interfície entre las dos áreas está bien definida en la capa de enlace, con un canal de comunicación especial para la interacción de tipo mosix_link.



El tiempo de migración tiene dos componentes:

Para minimizar el tráfico de migraciones sólo se transfieren las tablas de páginas y las páginas ocupadas por los procesos.

Las llamadas al sistema son una forma síncrona de interacción entre las dos áreas. Todas las que son ejecutadas por el proceso son interceptadas por la capa de enlace del remoto. Si la llamada de sistema no depende del UHN se ejecuta -localmente- en el nodo remoto. Si no, la llamada de sistema es redirigida al deputy el cual ejecuta la llamada a sistema del proceso.

Otras formas de interacción entre las dos áreas son la entrega de señales y los eventos para reactivar procesos, a medida que lleguen datos por la red. Estos eventos requieren que el deputy localice e interaccione asíncronamente con el remoto.

Este requisito de localización mosix_link es resuelto por el canal de comunicaciones existente entre ellos. En un escenario típico, el kernel del UHN informa al deputy del evento. Remote monitoriza el canal de comunicación para percatarse de eventos asíncronos, como pudieran ser señales, justo antes de volver a la ejecución de nivel de usuario.

Una desventaja es la sobrecarga en la ejecución de las llamadas al sistema y sobretodo por accesos a la red. Todos los enlaces de red -sockets- son creados en el UHN, así se impone comunicación a través de ellos si el proceso migra fuera del UHN. Para solucionar este problema el equipo de la Universidad Hebrea está desarrollando los socketa migrables, los cuales migran con el proceso y así permite un enlace directo entre los procesos migrados. Normalmente esta carga que añadimos puede reducirse significativamente con una distribución inicial de los procesos de comunicación en nodos diferentes, como en PVM. Si el sistema se desequilibra, los algoritmos de openMosix reasignarán los procesos para mejorar la eficiencia del sistema.

Los algoritmos para la compartición adaptativa de recursos

Los algoritmos de compartición de recursos en openMosix son dos:
  1. el de equilibrado dinámico de carga: Load Balancing,
  2. y el encargado de la gestión de memoria: Memory Ushering.



I.- LOAD BALANCING



El algoritmo de equilibrado dinámico de carga continuamente intenta reducir la diferencia de carga entre pares de nodos, migrando procesos desde los más cargados hacia los menos cargados, independientemente del par de nodos. El número de procesadores de cada nodo y su velocidad son factores importantes para tomar este tipo de decisiones. Este algoritmo responde a cambios en la carga de los nodos o a las características en la ejecución de los procesos. A lo largo de este proceso de toma de decisiones prevalece el porcentage de memoria libre o la carga de procesos y no la escasez de recursos.



II.- MEMORY USHERING



Memory Ushering inspira su nombre en una pol´ tica que los desarrolladores de openMosix llaman prevención de agotamiento. Intenta disponer el máximo número de procesos en la RAM del sistema -entendiéndose la totalidad de la memoria del cluster- para evitar en lo posible el thrashing y el swapping de los procesos. El algoritmo se invoca cuando un nodo empieza una paginación excesiva, debida generalmente a una escasez de memoria libre.

Acceso a ficheros

Uno de los mayores problemas de los clusters SSI es que cada nodo tiene que ser capaz de ver el mismo sistema de ficheros que cualquier otro nodo. Pongamos por ejemplo un programa que abre el fichero /tmp/moshe para escritura y lectura, y luego este proceso migra a otro nodo del cluster. El fichero en cuestión deberá ser capaz de permanecer como de lectura y escritura.

Hasta ahora había dos opciones para hacer esto. Una es que el cluster openMosix interceptara todas las E/S de los trabajos migrados, y las reenviara a su correspondiente UHN para su procesamiento posterior.

Alternativamente podría crearse una visión global de un sistema de ficheros a través de NFS. La primera es más difícil de desarrollar, pero más fácil de gestionar. La segunda es más fácil de implementar, pero puede ser un rompecabezas montar todos los sistemas de ficheros de manera inteligente, permitiendo que cada nodo pueda acceder a cualquier otro nodo. Adicionalmente, se tendría que asegurar que todos los identificadores de usuario y de grupo son consistentes entre todos los nodos del cluster, de otro modo nos toparíamos con serios problemas de permisos.

Buscando entre las mejores investigaciones de los modernos sistemas de ficheros y aplicando estas ideas a openMosix surgió DFSA (Direct File System Access). El DFSA fue diseñado para reducir el exceso de carga de la ejecución de llamadas de sistema orientadas a E/S de los procesos migrados. Esto se consiguió permitiendo la ejecución de la mayoría de llamadas a sistema de forma local, es decir, en el nodo donde se encuentre el proceso. En adición a DFSA se generó un nuevo algoritmo que hace un recuento de las operaciones de E/S. Este algoritmo se basa en que a un proceso que requiera un número medio/alto de operaciones de E/S se le tiende a migrar al nodo donde realizará la mayoría de estas operaciones. Una ventaja obvia es que los procesos de E/S tienen mayor flexibilidad para migrar desde su respectivo UHN para mejorar el equilibrado de carga. No obstante, a diferencia de NFS que sirve los datos desde el servidor hacia los nodos, openMosix intentará migrar el proceso al nodo en el que el fichero resida en aquel momento.

La implementación

Mecanismos en el remote y en el deputy

El deputy es la parte que representa al proceso remoto en el UHN. Debido a que la totalidad del espacio de usuario en memoria reside en el nodo remoto, el deputy no mantiene un mapa de memoria de él mismo. En lugar de esto comparte el mapa principal del kernel de forma similar a una hebra del kernel.

En algunas actividades del kernel, como pueden ser la ejección de las llamadas de sistema, se hace necesario transferir datos entre el espacio de usuario y el espacio de kernel. En openMosix cualquier operación de memoria del kernel que implique acceso al espacio de usuario requiere que el deputy comunique con su correspondiente remote para transferir los datos necesarios.

Con el fin de poder eliminar excesivas copias remotas se implementó una cache especial que reduce el número de interacciones requeridas con pre-fetching, transfiriendo el mayor volumen de datos posible durante la petición inicial de llamada a sistema, mientras se almacenan datos parciales en el deputy para devolverlos al remoto al final de la llamada a sistema.

Los procesos remotos no son accesibles por los otros procesos que se ejecutan en el mismo nodo y vice versa. No pertenecen a ningún usuario en particular en el nodo donde se ejecutan ni pueden recibir señales desde el nodo en el que se estan ejecutando. Su memoria no puede ser accedida y solo pueden ser forzados, por parte del propio administrador del nodo en el que se están ejecutando, a migrar fuera del nodo.

Cuando no puede aplicarse la migración

Ciertas funciones del kernel de Linux no son compatibles con la división de áreas de los procesos, para que estas se ejecuten remotamente. Algunos ejemplos obvios son las manipulaciones directas de dispositivos de E/S, tales como accesos directos a instrucciones privilegiadas del bus de E/S, o el acceso directo a la memoria del dispositivo. Otros ejemplos incluyen memoria compartida de escritura y planificadores a tiempo real.

Un proceso que usa alguna de estas funciones es asignado indefinidamente a su UHN. Si el proceso ya había estado migrado, se retorna al UHN.

Muestreo de información

Las estadísticas acerca del comportamiento del cluster son muestreadas regularmente. Estas incluyen todas las llamadas de sistema o cada vez que un proceso accede a datos de usuario. Esta información es usada para determinar si el proceso debe devolverse a su UHN. Estas estadísticas caducan en el tiempo, para ajustarse a procesos que cambian su perfil de ejecución.

Cada proceso tiene cierto control sobre el muestreo de información y sobre la caducidad de sus estadísticas. Toda la información acerca del API de openMosix puede encontrarse en la sección El API de openMosix.


miKeL a.k.a.mc2 2004-09-06