Los procesadores se pueden diseñar usando distintas filosofías de diseño. Entre todas ellas, hoy nos detendremos en la canalización (pipeline) y en la arquitectura superescalar. Te explicamos qué es cada una de ellas y cómo puede ayudar a los procesadores a tener un mejor rendimiento.
Índice de contenidos
¿Qué es un diseño canalizado o pipeline en un procesador?
La arquitectura canalizada, también conocida como pipeline, es una técnica de diseño de procesadores que busca optimizar el rendimiento mediante la superposición de la ejecución de instrucciones. Se puede apreciar tanto en CPUs, como GPUs, y otras unidades.
En lugar de ejecutar las instrucciones de forma secuencial, una por una, la arquitectura canalizada divide el proceso de ejecución en etapas independientes, cada una de las cual puede trabajar de forma independiente a las otras. De esta forma, las instrucciones fluyen a través de estas etapas como si estuvieran en una tubería (pipeline), de ahí el nombre de la técnica.
La implementación física implica la inserción de registros entre las etapas del pipeline. Estos registros almacenan los datos intermedios y los resultados parciales de la etapa anterior, permitiendo que las siguientes etapas accedan a ellos sin necesidad de esperar a que termine todo el proceso de ejecución completo de la instrucción.
Según la microarquitectura o diseño, se pueden tener más o menos estapas desacopladas, como por ejemplo:
- Captura de instrucción (Fetch): esta parte del Front-end del procesador se encarga de buscar la instrucción en la memoria y se carga en el registro de instrucción.
- Decodificación (Decode): si se interpone un registro entre la parte Fetch y esta otra, la parte anterior puede almacenar el resultado en dicho registro y liberarse para comenzar con el ciclo de búsqueda de la siguiente instrucción. Mientras tanto, en esta otra etapa se decodifica la primera instrucción y se obtienen los operandos de los registros o de la memoria.
- Ejecución (Execute): si se incluyen registros entre Decode y Execute, se puede almacenar el resultado parcial del decodificado, y de esa manera se libera para poder decodificar la siguiente instrucción que previamente había comenzado su ciclo fetch cuando éste fue liberado. Ahora, la primera instrucción se ejecuta mediante una operación aritmética o lógica especificada, obteniéndose el resultado.
- Acceso a memoria (Memory): se accede a la memoria para leer o escribir datos, si la instrucción lo requiere.
- Escritura de resultados (Write Back): se almacenan los resultados de la ejecución en los registros o en la memoria.
Como ves, la inclusión de registros entre cada una de esas etapas permite que se desacomplen y puedan trabajar con la siguiente instrucción aunque la primera no haya terminado. Por ejemplo, imagina un programa que consta de 5 instrucciones llamadas A, B, C, D y E:
- Procesador sin pipeline: cuando se accede a la instrucción A y entra en el procesador, se debe decodificar, ejecutar y escribir en memoria para poder introducir B, y así sucesivamente.
- Procesador con pipeline: cuando A termina el ciclo fetch, pasará al ciclo Decode, y se puede comenzar el ciclo fetch de la B. Cuando termine el ciclo en el que se encuentran A y B ahora, A pasará a la ejecución, y Decode procesará la instrucción B, mientras fetch va a por C, y así sucesivamente.
Las etapas de la pipeline pueden ser más o menos, dependiendo de cada diseño. Los procesadores modernos son diseños hipercanalizados, pueden tener entre 9 y 30 etapas o más, dependiendo de su arquitectura y complejidad. Además de las etapas descritas anteriormente, en las que he cogido un MIPS de ejemplo con 5 etapas, puede haber otras como:
- Cambio de contexto: guarda y restaura el estado del procesador al cambiar de tarea o subrutina.
- Predicción de saltos: predice si una instrucción de salto se ejecutará para iniciar la ejecución de las instrucciones objetivo.
- Reordenamiento de instrucciones: reordena las instrucciones para optimizar la ejecución.
- Ejecución especulativa: ejecuta instrucciones antes de confirmar si son necesarias, aumentando el rendimiento potencial.
- Retirada de resultados: retira los resultados de las unidades de ejecución y los almacena en los registros.
- Etapa de sincronización: eincroniza las diferentes unidades del procesador.
Por otro lado, las unidades funcionales, como las de ejecución, también se pueden canalizar. Esto significa que pueden realizar operaciones simultáneamente en diferentes etapas del pipeline. Por ejemplo, una unidad de cálculo podría estar realizando varios cálculos si se divide en varias etapas, en operaciones más pequeñas.
Ejemplos actuales del número de etapas de procesadores actuales son Intel Raptor Lake con 20 etapas de pipeline, AMD Zen 3 con 16 etapas, el Apple M2 con 14, etc. En el caso de la GPU, tenemos ejemplos como la NVIDIA Ampere de 32, la AMD RDNA 2 con 35, y la Intel Xe con 47 etapas…
También deberías leer sobre los mejores procesadores del mercado
¿Qué es un diseño superescalar en un procesador?
La arquitectura superescalar es una técnica de diseño que en implementar más de una unidad funcional idéntica para así poder realizar varias instrucciones a la vez. Es decir, mientras la pipeline se basa en la división de etapas, la superescalar multiplica la cantidad de unidades posibles, permitiendo que se ejecuten varias instrucciones en paralelo. En los procesadores escalares solo existe una unidad de cada tipo, en estas otras puede haber dos, tres o más unidades replicadas.
Mientras en la pipeline el impacto en la superficie del silicio no es tan grande, en esta otra arquitectura sí que hay mayor impacto, ya que más unidades significa más transistores y más espacio en el chip. Sin embargo, la mejora de rendimiento merece la pena. Por ejemplo, imagina tener que ejecutar dos instrucciones A y B, y ambas son sumas de números enteros:
- Diseño escalar: se introduce A en el procesador y se ejecuta la suma por la ALU, luego se introduce B y se hace lo propio.
- Diseño superescalar: si imaginamos un diseño que tiene dos ALUs, entonces se puede introducir A y B, ya que existen dos unidades, por lo que A no ocupa todo el ancho de ejecución, y habrá sitio para ejecutar B simultáneamente.
Hay que decir que existe una limitación en este caso, y es que si A fuese una suma entera y B fuese una multiplicación de coma flotante, y el diseño cuenta con dos ALUs y una sola FPU, entonces A y B se podrían procesar simultáneamente, pero en este mismo caso, si A y B fuesen de coma flotante, entonces B tendría que esperar a que la FPU se libere para ejecutarse, mientras las ALUs no puede hacer nada…
No olvides leer nuestro artículo sobre la microarquitectura
¿Son incompatibles?
Una pregunta frecuente es si los dos diseños son incompatibles entre sí, y la verdad es que no. De hecho, los procesadores modernos tienen pipeline y son superescalares, para conseguir rendimientos superiores.
Mientras la pipeline divide el proceso en etapas independientes, reduciendo la latencia y mejorando la eficiencia de uso de los recursos, la superescalar permite ejecuciones simultáneas, aumentando el paralelismo.
Si tienes dudas o preguntas al respecto, deja tus comentarios…