En ingeniería informática , la canalización de instrucciones es una técnica para implementar paralelismo a nivel de instrucciones dentro de un solo procesador. La canalización intenta mantener cada parte del procesador ocupada con alguna instrucción dividiendo las instrucciones entrantes en una serie de pasos secuenciales (la " canalización " del mismo nombre) realizados por diferentes unidades de procesador con diferentes partes de instrucciones procesadas en paralelo.
En una computadora canalizada, las instrucciones fluyen a través de la unidad central de procesamiento (CPU) en etapas. Por ejemplo, podría tener una etapa para cada paso del ciclo de von Neumann : buscar la instrucción, buscar los operandos, ejecutar la instrucción, escribir los resultados. Una computadora canalizada generalmente tiene "registros de canalización" después de cada etapa. Estos almacenan información de las instrucciones y cálculos para que las puertas lógicas de la siguiente etapa puedan realizar el siguiente paso.
Esta disposición permite que la CPU complete una instrucción en cada ciclo de reloj. Es común que las etapas pares operen en un borde del reloj de onda cuadrada, mientras que las etapas impares operan en el otro borde. Esto permite un mayor rendimiento de la CPU que una computadora de varios ciclos a una velocidad de reloj determinada , pero puede aumentar la latencia debido a la sobrecarga adicional del proceso de canalización en sí. Además, aunque la lógica electrónica tiene una velocidad máxima fija, una computadora canalizada se puede hacer más rápida o más lenta variando el número de etapas en la canalización. Con más etapas, cada etapa hace menos trabajo, por lo que la etapa tiene menos retrasos desde las puertas lógicas y podría funcionar a una velocidad de reloj más alta.
Un modelo de computadora canalizado suele ser el más económico, cuando el costo se mide como puertas lógicas por instrucción por segundo. En cada instante, una instrucción se encuentra en una sola etapa del proceso y, en promedio, una etapa del proceso es menos costosa que una computadora de ciclos múltiples. Además, cuando se hace bien, la mayor parte de la lógica de la computadora canalizada está en uso la mayor parte del tiempo. Por el contrario, las computadoras averiadas suelen tener grandes cantidades de lógica inactiva en un instante dado. Cálculos similares suelen mostrar que una computadora canalizada utiliza menos energía por instrucción.
Sin embargo, una computadora canalizada suele ser más compleja y costosa que una computadora multiciclo comparable. Normalmente tiene más puertas lógicas, registros y una unidad de control más compleja. De manera similar, podría usar más energía total, mientras usa menos energía por instrucción. Las CPU fuera de servicio normalmente pueden realizar más instrucciones por segundo porque pueden realizar varias instrucciones a la vez.
En una computadora canalizada, la unidad de control organiza el flujo para que se inicie, continúe y se detenga según lo ordene un programa. Los datos de las instrucciones generalmente se pasan en registros de canalización de una etapa a la siguiente, con una parte de lógica de control algo separada para cada etapa. La unidad de control también asegura que las instrucciones en cada etapa no perjudiquen el funcionamiento de las instrucciones en otras etapas. Por ejemplo, si dos etapas deben utilizar el mismo dato, la lógica de control garantiza que los usos se realicen en la secuencia correcta.
Cuando funciona de manera eficiente, una computadora canalizada tendrá una instrucción en cada etapa. Luego trabaja en todas esas instrucciones al mismo tiempo. Puede finalizar aproximadamente una instrucción por cada ciclo de su reloj. Pero cuando un programa cambia a una secuencia diferente de instrucciones, la canalización a veces debe descartar los datos en proceso y reiniciarse. Esto se llama "estancamiento".
Gran parte del diseño de una computadora canalizada evita la interferencia entre las etapas y reduce las pérdidas.
El número de pasos dependientes varía según la arquitectura de la máquina. Por ejemplo:
A medida que la canalización se hace "más profunda" (con un mayor número de pasos dependientes), un paso determinado se puede implementar con circuitos más simples, lo que puede permitir que el reloj del procesador funcione más rápido. [3] Estos oleoductos pueden denominarse superductos. [4]
Se dice que un procesador está completamente canalizado si puede obtener una instrucción en cada ciclo. Por lo tanto, si algunas instrucciones o condiciones requieren retrasos que inhiben la obtención de nuevas instrucciones, el procesador no está completamente canalizado.
Los usos fundamentales de la canalización se dieron en el proyecto ILLIAC II y el proyecto IBM Stretch , aunque anteriormente se utilizó una versión simple en el Z1 en 1939 y el Z3 en 1941. [5]
La canalización comenzó en serio a finales de la década de 1970 en supercomputadoras como los procesadores vectoriales y los procesadores de matriz. [ cita necesaria ] Una de las primeras supercomputadoras fue la serie Cyber construida por Control Data Corporation. Su arquitecto principal, Seymour Cray , dirigió más tarde Cray Research. Cray desarrolló la línea XMP de supercomputadoras, utilizando canalización para funciones de multiplicación y suma/resta. Más tarde, Star Technologies añadió el paralelismo (varias funciones canalizadas trabajando en paralelo), desarrollado por Roger Chen. En 1984, Star Technologies añadió el circuito dividido por tuberías desarrollado por James Bradley. A mediados de la década de 1980, muchas empresas diferentes de todo el mundo utilizaban la canalización. [ cita necesaria ]
La canalización no se limitó a las supercomputadoras. En 1976, la computadora central de propósito general de la serie 470 de Amdahl Corporation tenía una tubería de 7 pasos y un circuito de predicción de ramas patentado. [ cita necesaria ]
El modelo de ejecución secuencial supone que cada instrucción se completa antes de que comience la siguiente; Esta suposición no es cierta en un procesador canalizado. Una situación en la que el resultado esperado es problemático se conoce como peligro . Imagine las siguientes dos instrucciones de registro para un procesador hipotético:
1: suma 1 a R52: copiar R5 a R6
Si el procesador tiene los 5 pasos enumerados en la ilustración inicial (el 'canal básico de cinco etapas' al comienzo del artículo), la instrucción 1 se recuperará en el momento t 1 y su ejecución se completará en t 5 . La instrucción 2 se recuperaría en t 2 y se completaría en t 6 . La primera instrucción podría depositar el número incrementado en R5 como su quinto paso (escritura de registro) en t 5 . Pero la segunda instrucción podría obtener el número de R5 (para copiar a R6) en su segundo paso (decodificar la instrucción y recuperar el registro) en el momento t 3 . Parece que la primera instrucción no habría incrementado el valor para entonces. El código anterior invoca un peligro.
Es posible que escribir programas de computadora en un lenguaje compilado no genere estas preocupaciones, ya que el compilador podría diseñarse para generar código de máquina que evite peligros.
En algunos de los primeros procesadores DSP y RISC, la documentación aconseja a los programadores evitar dichas dependencias en instrucciones adyacentes y casi adyacentes (llamadas ranuras de retardo ), o declara que la segunda instrucción utiliza un valor antiguo en lugar del valor deseado (en el ejemplo anterior, el El procesador podría copiar de forma contraria a la intuición el valor no incrementado) o declara que el valor que utiliza no está definido. Es posible que el programador tenga trabajo no relacionado que el procesador pueda realizar mientras tanto; o, para garantizar resultados correctos, el programador puede insertar NOP en el código, anulando en parte las ventajas de la canalización.
Los procesadores canalizados comúnmente usan tres técnicas para funcionar como se espera cuando el programador asume que cada instrucción se completa antes de que comience la siguiente:
Una desviación de la secuencia de instrucciones normal a menudo implica un peligro. A menos que el procesador pueda dar efecto a la bifurcación en un solo ciclo de tiempo, la canalización continuará obteniendo instrucciones de forma secuencial. No se puede permitir que dichas instrucciones surtan efecto porque el programador ha desviado el control a otra parte del programa.
Una rama condicional es aún más problemática. El procesador puede bifurcarse o no, dependiendo de un cálculo que aún no se ha producido. Varios procesadores pueden detenerse, intentar la predicción de bifurcación y pueden comenzar a ejecutar dos secuencias de programa diferentes ( ejecución ansiosa ), cada una asumiendo que la bifurcación se toma o no, descartando todo el trabajo relacionado con la suposición incorrecta. [a]
Un procesador con una implementación de predicción de bifurcación que normalmente realiza predicciones correctas puede minimizar la penalización de rendimiento derivada de la bifurcación. Sin embargo, si las ramas se predicen mal, puede generar más trabajo para el procesador, como eliminar de la canalización la ruta de código incorrecta que comenzó la ejecución antes de reanudarla en la ubicación correcta.
Los programas escritos para un procesador canalizado evitan deliberadamente la bifurcación para minimizar la posible pérdida de velocidad. Por ejemplo, el programador puede manejar el caso habitual con ejecución secuencial y bifurcarse sólo al detectar casos inusuales. El uso de programas como gcov para analizar la cobertura del código permite al programador medir con qué frecuencia se ejecutan realmente determinadas ramas y obtener información para optimizar el código. En algunos casos, un programador puede manejar tanto el caso habitual como el caso inusual con código sin ramificaciones .
A la derecha hay una canalización genérica con cuatro etapas: recuperación, decodificación, ejecución y reescritura. El cuadro gris superior es la lista de instrucciones en espera de ser ejecutadas, el cuadro gris inferior es la lista de instrucciones que han completado su ejecución y el cuadro blanco del medio es la canalización.
La ejecución es la siguiente:
Un procesador canalizado puede hacer frente a los peligros deteniéndose y creando una burbuja en el canal, lo que da lugar a uno o más ciclos en los que no sucede nada útil.
En la ilustración de la derecha, en el ciclo 3, el procesador no puede decodificar la instrucción violeta, quizás porque determina que la decodificación depende de los resultados producidos por la ejecución de la instrucción verde. La instrucción verde puede pasar a la etapa de ejecución y luego a la etapa de escritura posterior según lo programado, pero la instrucción violeta se detiene durante un ciclo en la etapa de recuperación. La instrucción azul, que debía recuperarse durante el ciclo 3, se detiene durante un ciclo, al igual que la instrucción roja posterior.
Debido a la burbuja (los óvalos azules en la ilustración), el circuito de decodificación del procesador está inactivo durante el ciclo 3. Su circuito de ejecución está inactivo durante el ciclo 4 y su circuito de escritura inversa está inactivo durante el ciclo 5.
Cuando la burbuja sale de la tubería (en el ciclo 6), se reanuda la ejecución normal. Pero ahora todo tiene un ciclo de retraso. Se necesitarán 8 ciclos (ciclos 1 a 8) en lugar de 7 para ejecutar completamente las cuatro instrucciones que se muestran en colores. [b]