Blog

Gestión multiprocesador en Velneo

Este artículo es el primero de una serie de dos, en los que se aborda de manera muy básica, los conceptos de ejecución multihilo y multiprocesador, así como sus implicaciones en la programación en general, y en el rendimiento de las aplicaciones desarrolladas con tecnología Velneo en particular.

En esta primera parte se trata de aclarar conceptos muy en boga hoy en día y que a veces se usan con cierta ambigüedad o incluso ligereza, y que constituirán la clave para entender las problemáticas, muchos más cercanas al programador de Velneo, que se abordan en la segunda parte del artículo.

En varias ocasiones se ha comentado en los foros de Velneo problemas de rendimiento aparecidos en máquinas multiprocesador; en concreto la casuística más habitual que se suele mencionar es la de un procesador al 100% de uso mientras el vServer prácticamente no responde a nuevas peticiones, y sin embargo el resto de procesadores del sistema están prácticamente sin utilizar. De hecho si se lanzan otras aplicaciones en la misma máquina responden perfectamente y se ejecutan en alguno de los otros procesadores. Otro escenario común que se ha comentado en alguna ocasión, es el mismo que el anterior pero con el agravante de que el procesador ocupado ni siquiera está al 100%. Para tratar de aclarar si esto es un problema de la tecnología o del programador, qué es lo que está ocurriendo realmente y qué se puede hacer para mejorar el rendimiento, comenzaremos por realizar algunas definiciones básicas:

Equipo multiprocesador: sistema con más un procesador físico.

Dual core: arquitectura que incluye, parcialmente, dos procesadores en un solo encapsulado. Parcialmente quiere decir que no todos los componentes hardware de una CPU están duplicados, los que no lo están, son compartidos por ambas unidades de procesamiento.

Hyper-Threading: arquitectura específica de Intel que permite que un único procesador físico presente al sistema los recursos que lo identifican como dos procesadores distintos.

SMP (Symmetric multiprocessing): arquitectura computacional que permite la asignación de cualquier recurso de procesamiento a cualquier proceso que se vaya a ejecutar (los sistemas servidores NT y posteriores de Microsoft, y gran parte de sistemas UNIX son ejemplos de sistemas SMP).

Multitarea o multitask: se refiere a la capacidad de un sistema operativo para ejecutar varios procesos de manera concurrente si el hardware subyacente es multiprocesador, o de manera aparentemente concurrente si no lo es (o usa hyper threading o dual core, aunque en algunos casos los sistemas dual core se comportan como multitarea real.)

Multitarea preferente: arquitectura de implementación de multitarea en la que es el propio sistema operativo (mediante un componente denominado «scheduler») el que gestiona la asignación de tiempo de uso de recursos de procesamiento a cada tarea, en base, entre otras cosas, a las prioridades asignadas a cada tarea. Los sistemas multitarea actuales (tanto real como aparente) usan casi todos este tipo de gestión.

Hilo o «thread» de ejecución: se trata de un bloque de código ejecutable que pertenece a un proceso más grande. La noción habitual de proceso en sí puede asimilarse a la de un hilo de ejecución, uno hilo por cada proceso, excepto en el caso de los denominados «procesos multihilo», en los cuales un mismo proceso contiene varios bloques de código ejecutable estructurados en más de un hilo de ejecución.

Gestión multiprocesador en Velneo 1 Gestión multiprocesador en Velneo 2

Nota: la imagen muestra los principios básicos de ejecución de procesos en sistemas operativos multitarea para máquinas de un solo procesador y de múltiples procesadores. Los colores representan datos e instrucciones de distintos procesos. Si en vez de procesos, pensamos en hilos tendremos el concepto de ejecución multihilo. Y si en vez de procesadores físicos pensamos en combinaciones de hardware/software que permiten emular dos unidaddes de procesamiento lógicas sobre un solo procesador físico, nos acercaremos a los rudimentos conceptuales de Hyperthreading y Dual Core.

La planificación de varios procesos por parte de los sistemas operativos multitarea para simular la concurrencia de los mismos, es algo a lo que estamos tan habituados que no le solemos dar importancia; sin ir más lejos simplemente con arrancar un motor de aplicaciones en una máquina con sistema operativo Microsoft Windows 2003 Server tendremos en ejecución simultánea no sólo el proceso VMotor.exe, sino otros procesos: servicios de sistema, módulos de drivers para dispositivos… Todos ellos son procesos que se están ejecutando de manera simultánea compartiendo unos recursos limitados de procesamiento, ya que aunque la máquina sea multiprocesador el número de procesos siempre es superior al de CPUs. El aumento del rendimiento viene derivado del hecho de que un proceso entra en la CPU y es expulsado de ella por el scheduler antes de que expire una cantidad de tiempo máxima (con ciertas excepciones, ya que este control sólo lo aplican al 100% los sistemas operativos denominados de «tiempo real»), dando paso a otro proceso (el siguiente en la lista de prioridades dinámicas que establece el scheduler); aunque la posibilidad de ejecutar varios procesos simultáneamente tiene ventajas evidentes, y de hecho sería imposible tener sistemas operativos de entorno gráfico sin usar la multitarea, podría parecer que este modo de actuar como mínimo disminuye el rendimiento de cada proceso individual, sino del sistema en general (cambiar de un proceso a otro consume tiempo y recursos, ya que hay que salvaguardar el estado del proceso saliente y recuperar el del proceso entrante), pero la realidad es que, salvo casos puntuales, cuando un proceso conserva durante un periodo prolongado de tiempo el control de la CPU, el uso de la misma es muy ineficiente, de hecho la mayor parte del tiempo el proceso está a la espera de resultados y no calculando. Por esta razón la conmutación entre procesos permite que la CPU siga trabajando mientras tenemos un proceso a la espera, aumentando el rendimiento global del sistema sin prácticamente penalizar a los procesos individuales.

Continuará…

13 thoughts on “Gestión multiprocesador en Velneo

  1. Excelente artículo.

    Como siempre, bien explicado y muy muy útil.

    Considero que este tipo de información nos viene fenomenal para nuestras aplicaciones. No todo es programar, sino saber aprovechar los recursos.

  2. Buenas tardes:

    El artículo me parece claro. Los programadores en Velneo estamos acostumbrados a no tener que pensar en estas cosas.

    Esperaremos al segundo artículo para saber más acerca de la multitarea en Velneo… ¿Habrá posibilidad de incrementar la prioridad de las tareas? ¿Algo así como la QOS?

    Un saludo,

    Fran.

  3. Todo muy claro, aunque me entra una duda.

    Así como tenemos un pipeline, un caché de instrucciones, y una cola de prefetch en la CPU para repartir opcodes en cada ciclo de reloj y optimizar el rendimiento, ¿no hay ninún balanceo de procesos multihilo?

    Quizás sea que en los compiladores actuales de C++ no se le está sacando el rendimiento apropiado al hard, porque creo que a nivel de juego de instrucciones si tendría que haber algo, ¿o estoy equivocado?

    Saludos

    José Luis Cuesta

  4. No son conceptos sencillos de explicar, y hay muchos niveles implicados -juego de instrucciones del procesador, capa del S.O., interfaz de usuario…-. Pero es un buen punto de partida para el siguiente artículo.

  5. Me parece muy interesante el articulo por las explicaciones que se dan. Pero igual que el sistema operativo es responsable de la gestión del sistema y por tanto del rendimiento, tan bien un buen uso por parte del administrador/usuario mejora el rendimiento. Tambien es responsabilidad del compilador (el que fuere) aprovechar los recursos del sistema (hard, s.o.) y facilitar al programador funciones para su mejor rendimiento. «Corresponde al conductor, dirigir correctamente el vehículo, pero si los mandos del mismo facilitan la conducción, el rendimiento y la eficiencia del conjunto seran mayores»

  6. Me parece muy interesante el articulo por las explicaciones que se dan. Pero igual que el sistema operativo es responsable de la gestión del sistema y por tanto del rendimiento, tan bien un buen uso por parte del administrador/usuario mejora el rendimiento. Tambien es responsabilidad del compilador (el que fuere) aprovechar los recursos del sistema (hard, s.o.) y facilitar al programador funciones para su mejor rendimiento. «Corresponde al conductor, dirigir correctamente el vehículo, pero si los mandos del mismo facilitan la conducción, el rendimiento y la eficiencia del conjunto seran mayores»

  7. Miguel Ángel Álvarez Rodríguez (Velneo)

    Muy buenas:

    En cuanto al tema de implementar prioridad de tareas que comenta Fran, no está contemplado dar esta posibilidad directa al desarrollador de Velneo; hacerlo iría un poco en contra de la filosofía tradicional de Velneo: sencillez y fiabilidad. Sin embargo, como todos los que ya desarrolláis con otros productos de Velneo sabéis, existen mecanismos indirectos a vuestra disposición para priorizar tareas: tareas en segundo y tercer plano, demonios, orientación transaccional… Determinadas partes de vuestro código pueden programarse, con ligeras alteraciones, para ejecutarse de una manera u otra, adquiriendo distintos grados de prioridad en tiempo de ejecución según el tipo de implementación elegida. Estos mecanismos se mantienen en la nueva plataforma V7, y probablemente se implementará alguno más.

    Me refiero ahora al comentario de José Luís sobre la gestión del balanceo de procesos multihilo; un par de apuntes:

    * Efectivamente como se comentará en la segunda parte del artículo, la secuencia de ejecución de procesos multithread es, salvo algunos aspectos muy concretos, pero muy importantes, idéntico a la de ejecución de procesos concurrentes, y por lo tanto están implicados los mismos elementos: scheduler, asignación de recursos preferente (el balanceo al que creo que te refieres)… Aquellos procesos definidos como multihilo en V7 obtendrán mayor rendimiento del subsistema hardware, y de hecho hoy en día ya lo hacen en la plataforma Velázquez v6.x. En V7 apostamos por extender la arquitectura multihilo a la mayor parte del código posible, siempre y cuando la integridad de los datos (el verdadero talón de Aquiles de la programación multihilo) no se vea comprometida.

    * Por otro lado comentarte que efectivamente la optimización del ciclo de procesado mediante el uso de más de una pipeline segmentada y de algoritmos de predicción estadística de próxima instrucción (de uso común desde la aparición de los procesadores Pentium) opera a nivel puramente de arquitectura de procesador, y por lo tanto no es directamente manipulable desde un lenguaje de nivel medio como puede ser C/C++. Evidentemente, como cualquier otro software de cierta calidad y complejidad, hemos introducido optimizaciones en el código a nivel de ensamblador, como por ejemplo las relativas al uso de variables atómicas convertidas a volátiles para evitar su alojo en caché; sin embargo el uso de las librería QT y nuestro objetivo de conseguir un producto independiente de la plataforma nos limita mucho en el uso de este tipo de optimizaciones dependientes del hardware. Si que es cierto que existen unas directrices principales de programación relativas al uso de sentencias básicas condicionales en el código que afectan al rendimiento en pipelines segmentadas; dichas directrices son seguidas por el equipo de desarrollo de Velneo, pero esto no supone una gran novedad, y todos los equipos de programación de nivel medio las usan, salvo requerimientos específicos que las desaconsejen. En cualquier caso las mejoras que tu comentas dependen especialmente de la arquitectura subyacente, y son implementadas por los compiladores; pocas mejoras podemos aportar desde el equipo de desarrollo que aumenten el ratio de «acierto» en los pronósticos de la CPU 😉 Por otro lado algunos intentos de mejora en el proceso determinista de opcodes, como los usados por la implementación de byte code de Java, por ejemplo, no han provocado mejoras mensurables en el rendimiento, y su uso responde más bien al intento de obtener un marco de ejecución de código independiente de la plataforma hardware, cosa que tanto Java como nosotros hemos conseguido, aunque basándonos en procesos distintos.

    Y por último, y respondiendo al post que trataba sobre la responsabilidad del programador en el aprovechamiento de los recursos hardware para obtener el mayor rendimiento posible de las aplicaciones, comentar que en Velneo esta responsabilidad es doble. Por un lado el equipo de desarrollo de Velneo orienta todo su trabajo hacia la obtención del máximo rendimiento de la plataforma, pero es también objetivo prioritario el no comprometer la estabilidad. Confiar en que tenemos estas dos directrices básicas de trabajo presentes en todo momento, no es pediros que hagáis un acto de fe, ya que de muchos de vosotros es conocido el buen hacer en este sentido de nuestro arquitecto Juan Muñoz-Cobos. La segunda responsabilidad es efectivamente aquella a la que te refieres: la del programador que usa la plataforma Velneo. En este sentido estamos tan interesados como vosotros en que se programe de la manera más eficiente usando Velneo, ya que en este mundo nuestro el «boca a boca» funciona … ¡y de qué manera! La plataforma os proporcionará mecanismos indirectos, como los ya comentados anteriormente, para que podáis afinar vuestro código, pero además os proporcionaremos información útil en este sentido, como manuales de estilo, guías de optimización, artículos específicos sobre técnicas avanzadas de programación en Velneo… Como tú muy bien dices parte de esta responsabilidad es vuestra, pero también en ello queremos, y nos interesa, ayudaros.

  8. Gracias Miguel Angel por tu instructiva aclaración (ha sido practicamente otro artículo).

    Ya por simple curiosidad, para el siguiente artículo si es posible, me gustaría que nos informaras si en V7 se encargará QT de gestionar los diferentes hilos, ya que actualmente en 6.3 supongo que MFC está tirando de la API de Windows.

    Saludos

    José Luis Cuesta

Dejar un comentario