Breve historia del multiproceso
Del CISC al MPP
Desde siempre los diseñadores de arquitecturas de ordenadores han tenido un reto en mente: hacer que los ordenadores fueran cada vez más rápidos, más potentes en prestaciones y más baratos. Uno de los caminos para lograr este objetivo ha sido la vía del multiproceso.
Inicialmente, allá por los años 60, el objetivo de los diseñadores era fabricar un hardware que facilitase su uso por los programadores de entonces, que utilizaban para su trabajo el lenguaje máquina (assembler). Con esta premisa se diseñaron arquitecturas como la de los ordenadores IBM 360, con gran número de instrucciones (más de 400) de diferentes formatos y longitudes (algunas de ellas muy sofisticadas como el calcular el CRC de un bloque de datos), pero siempre con la idea en mente de ayudar al programador.
Para poder implementar esta variedad de instrucciones, formatos, etc., se realiza un uso extensivo de la microprogramación, como un nivel intermedio (firmware) que facilita el poder implementar estas arquitecturas complejas dentro de la lógica digital.
Así tenemos ejemplos de estas máquinas como el IBM 360/370/390, el PDP11/VAX11, el Intel 8080/8086/80x86, el Motorola 68000, etcétera. Esto es lo que hoy en día se denomina arquitecturas CISC (Complex Instruction Set Computers)
En la década de los setenta, varios investigadores en los laboratorios IBM y en el la Universidad de California en Berkeley, descubren lo que ellos denominan el efecto 80/20, o sea, que el 20 por ciento de las instrucciones se ejecutan el 80 por ciento del tiempo. Este fenómeno induce la idea de construir ordenadores o chips, que sólo incluyan aquellas instrucciones simples que se ejecutan la mayor parte del tiempo, de forma que el resto de las instrucciones se ejecuten por software como una combinación de esas otras instrucciones simples. El objetivo de este planteamiento de diseño es que todas las instrucciones se ejecuten en un solo ciclo de reloj, con un diseño LOAD/STORE, un solo formato y que sean unos chips fáciles de fabricar con la tecnología que entonces se empezaba a investigar (tecnología CMOS). A estos condicionantes se unía que por aquel entonces (finales de los 70) cada vez se usaba menos el lenguaje ensamblador, por lo que no era necesario diseñar una arquitectura con un juego de instrucciones fáciles de usar, ya que la mayor parte de los programas se escribían en lenguajes de alto nivel como Cobol, C, 4GL, etc. Este es el origen de las arquitecturas RISC (Reduced Instruction Set Computers)
Más rápido
Independientemente de que se usen arquitecturas CISC o RISC, los diseñadores de ordenadores se enfrentan al problema de como hacer que un ordenador sea más rápido, y las soluciones son tres:
- Aumentar la velocidad del reloj (MHz de la CPU)
- Aumentar el nivel de pipelining
- Aumentar el nivel de superscalar
Aumentar la velocidad del reloj, es la idea más simple, pero su implementación no es sencilla. La idea en la que se basa es que si en una CPU se ejecuta una instrucción (en el caso de RISC) o varias instrucciones (en el caso de CISC) si hacemos que el reloj vaya más rápido, se ejecutarán los programas más rápidamente. Ahora bien; esto no es tan sencillo como parece. Al aumentar la velocidad del reloj, los tiempos de travesía dentro de los propios chips, ya no son despreciables, y se empiezan a producir problemas por ecos de señal dentro del chip. La solución es hacer que los chips sean cada vez más pequeños, con lo cual puede obviarse este problema, pero ello conlleva procesos de fabricación cada vez más complejos.
Pipelining
La segunda vía de optimización es la del pipelining, que consiste en la ejecución en paralelo de las diferentes tareas que componen una instrucción (recuperar la instrucción desde memoria, decodificarla, recuperar los operandos, ejecutarla y almacenar los resultados). Estas tareas se pueden hacer como en tubos (pipes) en paralelo, de tal modo que cuando se ejecuta la tarea 3 de una instrucción, a la vez tiene lugar la tarea 2 de la siguiente instrucción, y la tarea 1 de la instrucción siguiente a la siguiente. Esta técnica está altamente desarrollada y todos los chips modernos la usan en su máxima extensión.
Superscalar
La tercera vía de optimización es la del superscalar, que es la ejecución de varias instrucciones a la vez en un solo ciclo de CPU. Esta es una idea interesante, pues permite multiplicar por tres o por cuatro la velocidad efectiva de la CPU. Ahora bien, también tiene sus problemas y sus límites. Si al ejecutar varias instrucciones a la vez, una de ellas es una bifurcación, las instrucciones que le siguen puede que no tengan que ejecutarse, con lo cual, si se ejecutan, hay que echarlas para atrás. Esta situación se puede mejorar con compiladores inteligentes, que reordenan parte del código para minimizar estas situaciones y por procesadores inteligentes que especulan acerca de cuál puede ser la bifurcación (recordando las bifurcaciones anteriores) y optimizan esta situación. Ahora bien, esta optimización tienes sus límites: se sabe que a partir de un nivel determinado de superscalar (cuando se ejecutan seis instrucciones a la vez) la eficiencia baja mucho, y ya no resulta rentable.
Una vez llegados a los límites tecnológicos, los diseñadores de ordenadores se plantean que un nuevo método para aumentar el rendimiento de un ordenador: utilizar más de un procesador en dos posibles alternativas:
- Soluciones SMP (Symmetric Multi Processing)
- Soluciones MPP (Massive Paralell Processing)
SMP
La solución SMP consiste en unir varios procesadores en un mismo sistema, compartiendo la memoria (excepto la primera página que se usa para control del procesador), los canales, unidades E/S, etcétera. En una arquitectura SMP existen varios programas (tareas) ejecutándose físicamente a la vez, de forma que cada porción de un programa puede ser ejecutado por diferentes procesadores. En las soluciones SMP, la CPU es un recurso más del sistema operativo, que se gestiona a base de colas como cualquier recurso más (memoria, unidades E/S, etc.) Para poder implementar esta solución por parte del sistema operativo, la arquitectura del procesador tiene que tener instrucciones de control de la CPU, y el concepto de identidad y propiedad del procesador, de tal modo que el sistema operativo pueda asignar el recurso a una tarea. Así, por ejemplo, el chip Pentium tiene instrucciones de control de multiproceso, pero no el procesador 80486, por lo que sólo pueden fabricarse sistemas SMP con Pentiums y no con 80486s. Las soluciones SMP están muy de actualidad hoy en día. De hecho, estamos asistiendo al proceso de madurez de este tipo de solución, con implementaciones bastante potentes de hasta 16 CPUs en un sistema SMP con muy buenos rendimientos. Las limitaciones se encuentran cuando se trata de interconectar un gran número de CPUs dentro de un sistema, y los problemas vienen esencialmente por dos vías: el control de recursos (spins locks) y la coherencia de los cachés.
El primer problema se refiere al hecho de que los recursos que son comunes a todas las CPUs, hay que protegerlos cuando se actualizan. Si hay muchas CPUs, se produce un cuello de botella a la hora de su uso y las CPUs gastan mucho tiempo esperando en que las otras CPUs terminen de hacer uso de esos recursos.
El segundo problema es la coherencia de los cachés. Las CPUs, para hacer un buen uso de las memorias, implementan unas memorias rápidas denominadas cachés, a menudo dentro del mismo chip que la CPU. Ahora bien, el hecho de que una página de memoria esté en el cache de una CPU (porque la está usando) plantea un problema de coherencia cuando otra CPU intensa usar esa página de memoria. Para solucionar este problema, los multiprocesadores implementan algún mecanismo para mantener la coherencia de esos ca